]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blob - cbios/sdio.180
interbank move via dma. (re)enable multisector transfer
[z180-stamp-cpm3.git] / cbios / sdio.180
1 TITLE 'sd disk handler'
2
3 ; CP/M-80 Version 3 -- Modular BIOS
4
5
6 ; Disk drive dispatching tables for linked BIOS
7
8 public sd0,sd1,sd2,sd3
9
10 ; Variables containing parameters passed by BDOS
11
12 extrn @adrv,@rdrv
13 extrn @trk,@sect,@cnt
14 extrn @dma,@dbnk
15
16 ; System Control Block variables
17
18 extrn @ermde ; BDOS error mode
19
20 ; Utility routines in standard BIOS
21
22 extrn ?wboot ; warm boot vector
23 extrn ?pmsg,pr.inln ; print message @<HL>, print inline message
24 extrn pr.crlf ; print <cr><lf>
25 extrn ?pderr ; print BIOS disk error header
26 extrn ?conin,?cono ; con in and out
27 extrn ?const ; get console status
28
29 extrn bnk2phy ;
30 extrn msg.sm ;
31 extrn msg.recv ;
32 extrn add_hla
33
34
35 ; Port Address Equates
36
37 include config.inc
38 include z180reg.inc
39
40 ; CP/M 3 Disk definition macros
41
42 include cpm3slr.lib
43
44 ; Z180 macro library instruction definitions (ignored by slr180)
45
46 include z180.lib
47
48 ; common control characters
49
50 cr equ 13
51 lf equ 10
52 bell equ 7
53
54
55 dseg
56
57 ; Extended Disk Parameter Headers (XPDHs)
58
59 dw sd$write
60 dw sd$read
61 dw sd$login
62 dw sd$init0
63 db 0,0 ; relative drive zero
64 sd0: dph 0,dpbsimhd512
65
66 dw sd$write
67 dw sd$read
68 dw sd$login
69 dw sd$init1
70 db 1,0 ; relative drive one
71 sd1: dph 0,dpbsimhd512
72
73 dw sd$write
74 dw sd$read
75 dw sd$login
76 dw sd$init2
77 db 2,0 ; relative drive zero
78 sd2: dph 0,dpbsimhd512
79
80 dw sd$write
81 dw sd$read
82 dw sd$login
83 dw sd$init3
84 db 3,0 ; relative drive one
85 sd3: dph 0,dpbsimhd512
86
87
88 cseg ; DPB must be resident
89
90 dpbsimhd512:
91 dpb 512,8,2048,4096,1024,6
92
93
94 dseg ; rest is banked
95
96 ; Disk I/O routines for standardized BIOS interface
97
98 ; Initialization entry point.
99 ; called for first time initialization.
100
101 sd$init0:
102 ret
103
104 sd$init1:
105 sd$init2:
106 sd$init3:
107 ret ; all initialization done by drive 0
108
109
110
111
112 ; This entry is called when a logical drive is about to
113 ; be logged into for the purpose of density determination.
114 ; It may adjust the parameters contained in the disk
115 ; parameter header pointed at by <DE>
116
117 sd$login:
118 xor a
119 ld (residual),a
120 ld hl,send_msg+1
121 ld (hl),0 ;login function
122 inc hl
123 ld bc,(@adrv)
124 ld (hl),c ;@adrv
125 inc hl
126 ld (hl),b ;@rdrv
127 inc hl
128
129 ex de,hl ;xdph to hl
130 xor a ;bank 0
131 call bnk2phy ;phys. linear address
132 ex de,hl
133 ld (hl),e
134 inc hl
135 ld (hl),d
136 inc hl
137 ld (hl),a
138
139 ld hl,send_msg
140 ld b,send_msg_login_len
141 call msg.sm
142
143 ld hl,recv_msg
144 ld b,recv_msg_len ; max receive message len
145 call msg.recv
146
147 ; ld a,(recv_msg_rc)
148 ; or a
149 ret ;
150
151
152
153 ; disk READ and WRITE entry points.
154 ; these entries are called with the following arguments:
155 ;
156 ; absolute drive number in @adrv (8 bits) +0
157 ; relative drive number in @rdrv (8 bits) +1
158 ; disk track address in @trk (16 bits) +2
159 ; disk sector address in @sect(16 bits) +4
160 ; multi sector count in @cnt (8 bits) +6
161 ; disk transfer address in @dma (16 bits) +7
162 ; disk transfer bank in @dbnk (8 bits) +9
163 ; pointer to XDPH in <DE>
164 ;
165 ; they transfer the appropriate data, perform retries
166 ; if necessary, then return an error code in <A>
167
168 sd$read:
169 ld de,read$msg ; point at " Read "
170 ld c,1
171 jr rw$common
172 sd$write:
173 ld de,write$msg ; point at " Write "
174 ld c,2
175 rw$common:
176
177 ld hl,residual ; remainng sectors from last multi io?
178 ld a,(hl)
179 sub a,1
180 jr c,rwc_new_sectors
181
182 ld (hl),a
183 xor a
184 ret
185
186 rwc_new_sectors:
187 ld b,1 ; assume 1 sector to transfer
188 ld a,(@cnt)
189 or a
190 jr z,rwc_doit
191
192 ld b,a ; number of sectors to transfer
193 dec a ; save remaining
194 ld (hl),a
195 xor a ; reset multi sector count
196 ld (@cnt),a
197
198 ; compute pysical transfer address
199 ; prepare message
200 ; and send it to AVR.
201
202 rwc_doit:
203 ld hl,send_msg+1
204 ld (hl),c
205 inc hl
206 ld a,b
207 ex de,hl
208 ld (operation$name),hl ; save message for errors
209 ld hl,@adrv ;address of arguments
210 ld bc,6
211 ldir
212 ld (de),a ;number of sectors
213 inc de
214 push de
215 ld e,(hl) ;dma address
216 inc hl
217 ld d,(hl)
218 inc hl
219 ld a,(hl) ;bank
220 ex de,hl
221 call bnk2phy ;phys. linear address
222 ex de,hl
223 pop hl
224 ld (hl),e
225 inc hl
226 ld (hl),d
227 inc hl
228 ld (hl),a
229
230 retry:
231
232 ld hl,send_msg
233 ld b,send_msg_rw_len
234 call msg.sm
235
236 ld hl,recv_msg
237 ld b,recv_msg_len ; max receive message len
238 call msg.recv
239 ld a,(recv_msg_rc)
240 or a
241 ret z ; check status and return to BDOS if no error
242
243 ; suppress error message if BDOS is returning errors to application...
244
245 ld a,(@ermde)
246 cp 0ffh
247 jr z,hard$error
248
249 ; Had permanent error, print message like:
250 ; BIOS Err on d: T-nn, S-mm, <operation> <type>, Retry ?
251
252 call ?pderr ; print message header
253
254 ld hl,(operation$name)
255 call ?pmsg ; last function (read or write)
256
257 ld a,(recv_msg_rc)
258 and a,07fh
259 jr z,fatfs_err
260
261 ld hl,drvmsg0 ; point at first driver error message
262 ld c,drvmsg_count
263 call pdecoded
264
265 fatfs_err:
266 ld a,(recv_msg_rc)
267 tst 080h
268 jr z,prompt ; no fatfs error
269
270 call pr.inln
271 db 'FatFs: ',0
272
273 ld hl,fr$msg0 ; point at first FatFs message
274 ld c,fr$msg$count
275 ld a,(recv_msg_rc+1)
276 call pdecoded
277
278 prompt:
279 call pr.inln
280 db ' Retry (Y/N) ? ',0
281
282 call u$conin$echo ; get operator response
283 cp 'Y'
284 jr z,retry ; Yes, then retry 10 more times
285
286 hard$error:
287 ; otherwise,
288 xor a
289 ld (residual),a
290
291 ld a,1 ; return hard error to BDOS
292 ret
293
294 cancel: ; here to abort job
295 jp ?wboot ; leap directly to warmstart vector
296
297
298
299 ; Print message to error code in A
300 ;
301
302 pdecoded:
303 push bc
304 push de
305 push hl ; put pointer to first message on stack
306 cp c
307 jr c,pdc_1
308 xor a
309 pdc_1:
310 ld bc,0
311 ld e,a ; save message number
312 xor a
313 inc e
314 pdc_nxt_str:
315 dec e
316 ex (sp),hl
317 jr z,pdc_found
318 ex (sp),hl
319 cpir
320 jr z,pdc_nxt_str
321 ; not found (should not happen)
322 pdc_found:
323 pop hl
324 call ?pmsg
325 pop de
326 pop bc
327 ret
328
329
330 ; get console input, echo it, and shift to upper case
331
332 u$conin$echo:
333
334 call ?const
335 or a
336 jr z,u$c1 ; see if any char already struck
337 call ?conin
338 jr u$conin$echo ; yes, eat it and try again
339 u$c1:
340 call ?conin
341 push af
342 ld c,a
343 cp ' '-1
344 call nc,?cono
345 pop af
346 cp 'a'
347 ret c
348 sub 'a'-'A' ; make upper case
349 ret
350
351
352 residual:
353 db 0
354
355 send_msg:
356 db 2 ; disk command
357 ds 1 ; subcommand (login/read/write)
358 ds 1 ; @adrv
359 ds 1 ; @rdrv
360 ; -read/write- -login-
361 ds 2 ; @trk xdph address
362 ds 2 ; @sect (3 byte)
363 ds 1 ; @cnt
364 ds 3 ; transfer addr
365 send_msg_rw_len equ $ - send_msg
366 send_msg_login_len equ 7
367
368
369 recv_msg:
370 ds 1 ; len
371 ds 1 ; command
372 ds 1 ; subcommand
373 recv_msg_rc:
374 ds 1 ; result code
375 ds 4 ; room for additional parameter
376 recv_msg_len equ $ - recv_msg
377
378
379 ; error message components
380
381 operation$name:
382 dw read$msg
383 read$msg:
384 db ', Read, ',0
385 write$msg:
386 db ', Write, ',0
387
388 drvmsg0: db 'Unknown Error, ',0
389 drvmsg1: db 'Invalid Parameter(s), ',0
390 drvmsg2: db 'Invalid Drive, ',0
391 drvmsg3: db 'Bus Timeout, ',0
392 drvmsg_size equ $ - drvmsg0
393 drvmsg_count equ 3
394
395
396 ; table of pointers to error message strings
397
398 fr$msg0: db 'Unknown Error,',0
399 fr$msg1: db 'DISK_ERR,',0
400 fr$msg2: db 'INT_ERR,',0
401 fr$msg3: db 'NOT_READY,',0
402 fr$msg4: db 'NO_FILE,',0
403 fr$msg5: db 'NO_PATH,',0
404 fr$msg6: db 'INVALID_NAME,',0
405 fr$msg7: db 'DENIED,',0
406 fr$msg8: db 'EXIST,',0
407 fr$msg9: db 'INVALID_OBJECT,',0
408 fr$msg10: db 'WRITE_PROTECTED,',0
409 fr$msg11: db 'INVALID_DRIVE,',0
410 fr$msg12: db 'NOT_ENABLED,',0
411 fr$msg13: db 'NO_FILE_SYSTEM,',0
412 fr$msg14: db 'MKFS_ABORTED,',0
413 fr$msg15: db 'TIMEOUT,',0
414 fr$msg16: db 'LOCKED,',0
415 fr$msg17: db 'NOT_ENOUGH_CORE,',0
416 fr$msg18: db 'TOO_MANY_OPEN_FILES,',0
417 fr$msg19: db 'FR_INVALID_PARAMETER,',0
418 fr$msg20: db 'short read/write,',0
419 fr$msg$size equ $ - fr$msg0
420 fr$msg$count equ 20
421
422 end