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