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していただいて良いですよ.