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