Last Updated on 2019年10月20日 by kabekin
BIOS09内のディスクI/Oのサブルーチンを考えています。
S1はFMと違い、ROM内にFDDのサブルーチンが無いので自分で作る必要があるみたいです。
FDCのMB8877を使った参考書としては「オーム社のマイクロコンピュータMC6809の考え方」が分かりやすくお気に入りの書籍です。
この本はFLEX9中心の参考書ですが、この本を参考にS1CPM用のディスクI/Oサブルーチンを考えてみました。
S1はMB8876なのですがデータの反転を入れればOKではないかと甘いことを考え中^^
骨格は書籍の通りですが、S1固有の部分を合わせながら進めています。
(MC6809の考え方ではDRQをIRQとしてMPUに取り込んでいますがS1ではDRQはMNIに取り込んでいないっぽい)
6809活用研究に掲載のMP-1870の回路図を見るとDRQ,IRQは$FF04のリードで取得することが判明
ドライブ変更時に正常に動作しなくなったり、セクタを変えると暴走したりと問題点満載ですが、コードを晒しながら動作するように頑張ります^^
何か勘違いしていると思いますので、間違いに気づかれた方はご指摘下さい(^^;;
(アセンブラはMS-DOS用のAS63_DOS.EXEを使ってます)
1 # MB-S1 DISKIO サブルーチン案3 2 0000 3 0200 SH_BASE equ $0200 #Z80との共通領域トップ(仮) 4 FFEB SYSMODE equ $FFEB #SYSMODEレジスタ 5 FF00 FDCTOP equ $FF00 #S1FDC Top Address 6 0000 7 0000 8 0000 org $0000 #先頭番地は仮に$0 9 0000 10 0000 START: equ * 11 0000 17 0033 lbsr FDCINIT 12 0003 13 0003 CC 0300 ldd #$0300 #Memory Address 14 0006 FD 0203 std $203 15 0009 86 14 lda #20 #Track 16 000B B7 0205 sta $205 17 000E 86 05 lda #5 #SectorNo 18 0010 B7 0206 sta $206 19 0013 86 00 lda #0 #Drive 20 0015 B7 0207 sta $207 21 0018 22 0018 17 0036 lbsr VALSET 23 001B 24 # lbsr RESTORE 25 # lbsr SEEK 26 001B 17 004E lbsr READSECT 27 001E 28 001E 86 01 lda #1 29 0020 17 0161 lbsr DRIVESET 30 0023 86 26 lda #39 31 0025 A7 8D 0008 sta wTrackNo,PCR 32 # lda #6 33 # sta wSectNo,PCR 34 0029 17 008E lbsr WRITESECT 35 002C 36 002C 39 rts 37 002D 38 002D 39 #----- FDC関連のサブルーチン --------------------------------------------------------- 40 #(オーム社 6809の考え方 p161-p166) 41 002D 42 # SH_BASE=ディスクパラメータの先頭アドレス 43 # 0,X=FDC Status/Command Reg. 44 # 1,X=Track Reg. 45 # 2,X=Sector Reg. 46 # 3,X=Data Reg. 47 # 4,X=S1 UnitSel 48 # (FDCEnable,FaultReset,DDEN,SIDE,- MOTOR,x,2^1,2^0) 49 002D 50 #SH_BASEより入出力のための情報とする 51 #内容 値 バイト数 オフセット 備考 52 #CMDNO 8 1 0 53 #IOSTAT - 1 1 54 #DATAREG - 1 2 55 #SH_BASE-1 メモリアドレス 0000H-0FFFFH 2 3 ビッグエンディアン 56 #SH_BASE-2 トラック番号 0-39 1 5 57 #SH_BASE-3 セクタ番号 1-32 1 6 58 #SH_BASE-4 ドライブ番号 0-3 1 7 59 #SH_BASE-5 セクタ数 1-255 1 8 60 #SH_BASE-6 FDCデータ - 256 9~ 61 002D 62 0080 RDCMD equ $80 #Read Command 63 00A0 WRCMD equ $A0 #Write Command 64 0010 SKCMD equ $10 #Seek Command 65 0000 RECMD equ $00 #Restore Command 66 002D 67 002D wDriveNo: rmb 1 #ドライブ番号 68 002E wSideNo: rmb 1 #Side番号(0/1) 69 002F wDensSel: rmb 1 #密度選択(0=倍/1=単) 70 0030 wMotorOn: rmb 1 #モータ(0=OFF/1=ON) 71 0031 wTrackNo: rmb 1 #トラック番号 72 0032 wSectNo: rmb 1 #セクタ番号 73 0033 wMemAdrs: rmb 2 #メモリアドレス 74 0035 wWork: rmb 1 #ワーク 75 0036 76 0036 77 #+++ S1/DDSD 変数初期化/パラメータセット 78 0036 FDCINIT: equ * 79 0036 86 20 lda #$20 80 0038 A7 8C F4 sta wDensSel,PCR #$20=倍密度 81 003B 6F 8C EF clr wDriveNo,PCR 82 003E 6F 8C ED clr wSideNo,PCR 83 0041 6F 8C EC clr wMotorOn,PCR 84 0044 6F 8C EA clr wTrackNo,PCR 85 0047 6F 8C E8 clr wSectNo,PCR 86 004A 6F 8C E6 clr wMemAdrs,PCR 87 004D 6F 8C E5 clr wWork,PCR 88 0050 39 rts 89 0051 90 0051 91 #+++ 変数セット(BIOS80からのパラメータ受取用) 92 0051 34 16 VALSET: pshs D,X 93 0053 8E 0200 ldx #SH_BASE 94 0056 EC 03 ldd 3,X 95 0058 ED 8C D8 std wMemAdrs,PCR 96 005B A6 05 lda 5,X 97 005D A7 8C D1 sta wTrackNo,PCR 98 0060 A6 06 lda 6,X 99 0062 A7 8C CD sta wSectNo,PCR 100 0065 A6 07 lda 7,X 101 0067 A7 8C C3 sta wDriveNo,PCR 102 006A 35 96 puls D,X,PC 103 006C 104 006C 105 #+++ 1セクタ(256バイト)読込 106 #引数=各変数 107 #X=FDCパラメータ領域(FDC先頭アドレス=$FF00) 108 #Y=ロード領域へのポインタ 109 #出力 = 結果AccA($00=正常終了, $FF=エラー) 110 006C READSECT: equ * 111 006C 34 34 pshs B,X,Y 112 006E 1A 50 orcc #$50 #割込禁止→NMIのみ受付け 113 0070 17 0175 lbsr CLK1M 114 0073 17 00A4 lbsr SEEK 115 0076 17 0093 lbsr CHKFDCRDY #FDC準備完了チェック 116 0079 8E FF00 ldx #FDCTOP 117 007C 10AE 8C B3 ldy wMemAdrs,PCR 118 0080 A6 8C AE lda wTrackNo,PCR 119 0083 43 coma 120 0084 A7 01 sta 1,X 121 0086 A6 8C A9 lda wSectNo,PCR 122 0089 43 coma 123 008A A7 02 sta 2,X 124 008C 86 80 lda #RDCMD 125 008E 43 coma 126 008F A7 84 sta 0,X #Command Reg. 127 0091 12 nop 128 0092 READSECTLP1: 129 0092 A6 04 lda 4,X #コマンド完了検出(IRQ) 130 0094 47 asra 131 0095 24 0B bcc READSECTLP2 132 0097 133 0097 E6 04 ldb 4,X #DRQセット待ち 134 0099 2B F7 bmi READSECTLP1 135 009B E6 03 ldb 3,X #データ読込 136 009D 53 comb 137 009E E7 A0 stb ,Y+ 138 00A0 20 F0 bra READSECTLP1 139 00A2 READSECTLP2: 140 00A2 4F clra 141 00A3 E6 84 ldb 0,X #FDCからステータス取得 142 00A5 53 comb 143 00A6 D4 1C andb 0b00011100 #Bit4=RECORD NOT FOUND, Bit3=CRC ERROR, Bit2=DATA LOSTをチェック 144 00A8 27 02 beq READSCTCOMP 145 00AA 86 FF lda #$FF 146 00AC READSCTCOMP: 147 00AC 6F 8C 81 clr wMotorOn,PCR 148 00AF 17 00DA lbsr UNITSEL 149 00B2 1C AF andcc #$AF #割込許可 150 00B4 17 0135 lbsr CLK2M 151 00B7 35 34 puls B,X,Y 152 00B9 39 rts 153 00BA 154 00BA 155 #+++ 1セクタ(256バイト)書込み 156 #引数=各変数 157 #X=FDCパラメータ領域(FDC先頭アドレス=$FF00) 158 #Y=ロード領域へのポインタ 159 #出力 = 結果AccA($00=正常終了, $FF=エラー) 160 00BA WRITESECT: equ * 161 00BA 34 34 pshs B,X,Y 162 00BC 1A 50 orcc #$50 #割込禁止→NMIのみ受付け 163 00BE 17 0127 lbsr CLK1M 164 00C1 17 0056 lbsr SEEK 165 00C4 17 0045 lbsr CHKFDCRDY #FDC準備完了チェック 166 00C7 8E FF00 ldx #FDCTOP 167 00CA 10AE 8D FF64 ldy wMemAdrs,PCR 168 00CF A6 8D FF5E lda wTrackNo,PCR 169 00D3 43 coma 170 00D4 A7 01 sta 1,X 171 00D6 A6 8D FF58 lda wSectNo,PCR 172 00DA 43 coma 173 00DB A7 02 sta 2,X 174 00DD 86 A0 lda #WRCMD 175 00DF 43 coma 176 00E0 A7 84 sta 0,X #Command Reg. 177 00E2 12 nop 178 00E3 WRITESECTLP1: 179 00E3 A6 04 lda 4,X #コマンド完了検出(IRQ) 180 00E5 47 asra 181 00E6 24 0B bcc WRITESECTLP2 182 00E8 183 00E8 E6 04 ldb 4,X #DRQセット待ち 184 00EA 2B F7 bmi WRITESECTLP1 185 00EC E6 A0 ldb ,Y+ 186 00EE 53 comb 187 00EF E7 03 stb 3,X 188 00F1 20 F0 bra WRITESECTLP1 189 00F3 WRITESECTLP2: 190 00F3 4F clra 191 00F4 E6 84 ldb 0,X #FDCからステータス取得 192 00F6 53 comb 193 00F7 D4 3C andb 0b00111100 #Bit5=WRITE FAULT Bit4=RECORD NOT FOUND, Bit3=CRC ERROR, Bit2=DATA LOSTをチェック 194 00F9 27 02 beq WRITESCTCOMP 195 00FB 86 FF lda #$FF 196 00FD WRITESCTCOMP: 197 00FD 6F 8D FF2F clr wMotorOn,PCR 198 0101 17 0088 lbsr UNITSEL 199 0104 1C AF andcc #$AF #割込許可 200 0106 17 00E3 lbsr CLK2M 201 0109 35 34 puls B,X,Y 202 010B 39 rts 203 010C 204 010C 205 #+++ FDC準備完了待ち 206 010C CHKFDCRDY: equ * 207 010C 34 16 pshs D,X 208 010E 8E FF00 ldx #FDCTOP 209 0111 CHKFDCRDYLP: 210 0111 E6 84 ldb 0,X #Status Reg 211 0113 53 comb 212 0114 C5 81 bitb #$81 #Bit7 Not Ready BitとBit0 Busyをチェック 213 0116 26 F9 bne CHKFDCRDYLP 214 0118 35 96 puls D,X,PC 215 011A 216 011A 217 #;+++ ヘッドSEEK 218 #入力 = wDriveNo, wTrackNo, wSectNo 219 #出力 = 結果AccA($00=正常終了, $FF=エラー) 220 011A SEEK: equ * 221 011A 34 14 pshs B,X 222 011C 8E FF00 ldx #FDCTOP 223 011F 17 00B0 lbsr SIDESEL 224 0122 A7 8D FF08 sta wSideNo,PCR 225 0126 A6 8D FF07 lda wTrackNo,PCR 226 012A 43 coma 227 012B A7 03 sta 3,X #DATAREG 228 012D 86 01 lda #$01 229 012F A7 8D FEFD sta wMotorOn,PCR 230 0133 17 0056 lbsr UNITSEL 231 0136 A7 04 sta 4,X 232 0138 12 nop 233 0139 86 10 lda #SKCMD 234 013B 43 coma 235 013C A7 84 sta 0,X #コマンドレジスタにコマンド書込み 236 013E 13 sync #シーク完了待ち(MNI) 237 013F 4F clra 238 0140 E6 84 ldb 0,X #ステータスレジスタから結果取得 239 0142 53 comb 240 0143 D4 18 andb 0b00011000 #Bit4 SEEK ERROR #Bit3 CRC ERRORをチェック 241 0145 27 02 beq SEEK1 242 0147 86 FF lda #$FF 243 0149 SEEK1: 244 0149 17 FFC0 lbsr CHKFDCRDY #FDC Ready待ち 245 014C 35 94 puls B,X,PC 246 014E 247 014E 248 #+++ レストア 249 #入力 = wDriveNo 250 #出力 = 結果AccA($00=正常終了, $FF=エラー) 251 014E RESTORE: equ * 252 014E 34 14 pshs B,X 253 0150 8E FF00 ldx #FDCTOP 254 0153 17 0092 lbsr CLK1M 255 0156 86 01 lda #$01 256 0158 A7 8D FED4 sta wMotorOn,PCR 257 015C 17 002D lbsr UNITSEL 258 015F A7 04 sta 4,X 259 0161 1A 50 orcc #$50 #割込禁止→NMIのみ受付け 260 0163 86 00 lda #RECMD 261 0165 43 coma 262 0166 A7 84 sta 0,X #Command Reg 263 0168 13 sync #レストア完了待ち(MNI) 264 0169 4F clra 265 016A E6 84 ldb 0,X #ステータスレジスタから結果取得 266 016C 53 comb 267 016D D4 18 andb 0b00011000 #Bit4 SEEK ERROR #Bit3 CRC ERRORをチェック 268 016F 27 02 beq RESTORE1 269 0171 86 FF lda #$FF 270 0173 RESTORE1: 271 0173 17 FF96 lbsr CHKFDCRDY #FDC Ready待ち 272 0176 6F 8D FEB6 clr wMotorOn,PCR 273 017A 17 000F lbsr UNITSEL 274 017D 17 006C lbsr CLK2M 275 0180 1C AF andcc #$AF #割込許可 276 0182 35 94 puls B,X,PC 277 0184 278 0184 279 #+++ ドライブ選択 280 #入力=AccAドライブ番号 281 #出力 = 結果AccA($00=正常終了, $FF=エラー) 282 0184 DRIVESET: equ * 283 0184 A7 8D FEA5 sta wDriveNo,PCR 284 0188 17 FFC3 lbsr RESTORE 285 018B 39 rts 286 018C 287 018C 288 #+++ UNITSEL設定 289 #UNITSEL($FF04)のビット割当て 290 # Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 291 #READ #DRQ N/A N/A N/A N/A N/A N/A #IRQ 292 #WRITE 0 NMIMASK DDEN HEAD1 MOTORON 0 Drv^1 Drv^0(MP-1805) 293 #WRITE #FDCENBL 8'RESET #DDEN HEAD1 MOTORON 0 Drv^1 Drv^0(S1/40) S1活研ではDDENが#になってる? 294 # 295 #入力 = wDensSel, [wSideNo], wMotorOn, wDriveNo,wSectorNo 296 #出力 = AccA (UNITSEL Bit) 297 018C UNITSEL: equ * 298 018C 34 04 pshs B 299 018E 86 00 lda #$00 #Bit7=0(FDC有効),Bit6=0(MNIMask/FaultReset),Bit5~0=0固定 300 0190 E6 8D FE9B ldb wDensSel,PCR 301 0194 58 aslb 302 0195 58 aslb 303 0196 58 aslb 304 0197 58 aslb 305 0198 58 aslb 306 0199 6F 8D FE98 clr wWork,PCR 307 019D E7 8D FE94 stb wWork,PCR 308 01A1 AA 8D FE90 ora wWork,PCR 309 01A5 E6 8D FE85 ldb wSideNo,PCR 310 01A9 58 aslb 311 01AA 58 aslb 312 01AB 58 aslb 313 01AC 58 aslb 314 01AD 6F 8D FE84 clr wWork,PCR 315 01B1 E7 8D FE80 stb wWork,PCR 316 01B5 AA 8D FE7C ora wWork,PCR 317 01B9 E6 8D FE73 ldb wMotorOn,PCR 318 01BD 58 aslb 319 01BE 58 aslb 320 01BF 58 aslb 321 01C0 6F 8D FE71 clr wWork,PCR 322 01C4 E7 8D FE6D stb wWork,PCR 323 01C8 AA 8D FE69 ora wWork,PCR 324 01CC AA 8D FE5D ora wDriveNo,PCR 325 01D0 35 84 puls B,PC 326 01D2 327 01D2 328 #+++ サイド選択(セクタ17以上は16を引いてwSectNoに戻す) 329 #入力 = wSectNo 330 #出力 = AccA SideNo $0 or $1), wSectNo 331 01D2 SIDESEL: equ * 332 01D2 A6 8D FE5C lda wSectNo,PCR #SectorNo 333 01D6 81 10 cmpa #16 334 01D8 22 02 bhi SIDE2SEL #16セクタ以上ならSide2 335 01DA 20 09 bra SIDE1SEL #それ以外ならSide1 336 01DC SIDE2SEL: 337 01DC 80 10 suba #16 338 01DE A7 8D FE50 sta wSectNo,PCR 339 01E2 86 01 lda #$01 340 01E4 39 rts 341 01E5 SIDE1SEL: 342 01E5 86 00 lda #$00 343 01E7 39 rts 344 01E8 345 01E8 346 #+++ #システムクロックを1MHzに指定 347 01E8 CLK1M: equ * 348 01E8 7F FFEB clr SYSMODE 349 01EB 39 rts 350 01EC 351 01EC 352 #+++ #システムクロックを2MHzに指定 353 01EC CLK2M: equ * 354 01EC 34 02 pshs A 355 01EE 86 02 lda #$02 356 01F0 B7 FFEB sta SYSMODE 357 01F3 35 82 puls A,PC Total Errors 0 Total labels 39
このソフトを実行するとドライブ0のトラック20,セクタ5を1セクタ読込んで$0300~にロードします。
$300~書き込まれた256バイトをドライブ1のトラック39、セクタ5に1セクタ書き込みます。
本来アセンブラのサブルーチンは上記のように機能毎に別の位置で処理するのではなく、
一連の流れでデータを作る効率の良さが求められるものだと思いますが、完全に機能毎に処理しています。
かなり非効率なポンコツプログラムですが笑って許してください^^;;
アセンブラのコードの書き方をマスタしたいので、こう書いたほうがいいなどの指摘がありましたら
どんどん指摘してください(^^;;;
連絡画面からのメール送信も復活させましたので、アドバイスなど宜しくお願い致します(^^)
ちょっとだけですが,
—
SIDESEL: equ *
lda wSectNo,PCR #SectorNo
bita #$10
bne SIDE2SEL #16セクタ以上ならSide2
SIDE1SEL: clra # lda #0よりclraの方が速い
rts # SIDE1ならwSectNo,PCRはそのままで良い
SIDE2SEL: anda #$0f
sta wSectNo,PCR
lda #$01
rts
—
お懐かしい!
あの Level3さん でしょうか!?
私は当時NIFTYのFOS9/FDEVICEに Hase. というハンドルで出没していました。
現在は
https://twitter.com/haserin09
http://haserin09.la.coocan.jp/
で細々とやっております。
ところで、ご相談させていただきたいことがあるのですが、DMさせていただいてもよろしいでしょうか?
以上、よろしくお願いします。
勝手に使ってしまってすいません。>かべきんさま
はい!私のブログで宜しければどんどん活用下さい(^^)
もう1つ,データエリアの参照にプログラムカウンタ相対を使用していますが,ここは絶対アドレス参照で良いのではないでしょうか?BIOSの位置は出来上がった段階では固定ですから絶対アドレス参照の方が速いと思います.
コメントありがとうございます
SIDESELのサブルーチンは早速入替えさせて頂きました^^;;
現状は実験する際に$3000~ロードしたり$0000からロードしたりと相対アドレス対応でコーディングしていますが、ある程度動作するようになって落ち着いてきたら絶対アドレスにして速度重視に整理したいと思います
Haseさんですか? はい,Nifty FDEVICEのLevel3です.
DMしていただいて良いですよ.