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