]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blame_incremental - cbios/sdio.180
Support new error codes/messages: 'Write protected', 'No media', 'Access beyond disk...
[z180-stamp-cpm3.git] / cbios / sdio.180
... / ...
CommitLineData
1 TITLE 'sd disk handler'\r
2\r
3; CP/M-80 Version 3 -- Modular BIOS\r
4\r
5\r
6 ; Disk drive dispatching tables for linked BIOS\r
7\r
8 public sd0,sd1,sd2,sd3\r
9 public sd4,sd5,sd6,sd7\r
10\r
11 ; Variables containing parameters passed by BDOS\r
12\r
13 extrn @xdph\r
14 extrn @adrv,@rdrv\r
15 extrn @trk,@sect,@cnt\r
16 extrn @dma,@dbnk\r
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
25 extrn ?pmsg,pr.inln ; print message @<HL>, print inline message\r
26 extrn pr.crlf ; print <cr><lf>\r
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
57 dseg\r
58\r
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
78 dw sd$init2\r
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
85 dw sd$init3\r
86 db 3,0 ; relative drive one\r
87sd3: dph 0,dpbsimhd512\r
88\r
89\r
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
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
133 call pr.inln ;\r
134 db 'sdio: SD Card driver'cr,lf,0\r
135 ret\r
136\r
137sd$init1:\r
138sd$init2:\r
139sd$init3:\r
140sd$init4:\r
141sd$init5:\r
142sd$init6:\r
143sd$init7:\r
144 ret ; all initialization done by drive 0\r
145\r
146\r
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
151;\r
152; absolute drive number in @adrv (8 bits) +0\r
153; relative drive number in @rdrv (8 bits) +1\r
154\r
155sd$login:\r
156 xor a\r
157 ld (residual),a\r
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
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
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
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
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
210 ld de,read$msg ; point at " Read "\r
211 ld c,1\r
212 jr rw$common\r
213sd$write:\r
214 ld de,write$msg ; point at " Write "\r
215 ld c,2\r
216rw$common:\r
217\r
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
226\r
227rwc_new_sectors:\r
228 ld b,1 ; assume 1 sector to transfer\r
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
238\r
239; compute pysical transfer address\r
240; prepare message\r
241; and send it to AVR.\r
242\r
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
250 ld hl,@adrv ;address of arguments\r
251 ld bc,6\r
252 ldir\r
253 ld (de),a ;number of sectors\r
254 inc de\r
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
271retry:\r
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
299 and a,07fh\r
300 jr z,fatfs_err\r
301\r
302 ld hl,drvmsg0 ; point at first driver error message\r
303 ld c,drvmsg_count\r
304 call pdecoded\r
305\r
306fatfs_err:\r
307 ld a,(recv_msg_rc)\r
308 tst 080h\r
309 jr z,prompt ; no fatfs error\r
310\r
311 call pr.inln\r
312 db 'FatFs: ',0\r
313\r
314 ld hl,fr$msg0 ; point at first FatFs message\r
315 ld c,fr$msg$count\r
316 ld a,(recv_msg_rc+1)\r
317 call pdecoded\r
318\r
319prompt:\r
320 call pr.inln\r
321 db ' Retry (Y/N) ? ',0\r
322\r
323 call u$conin$echo ; get operator response\r
324 cp 'Y'\r
325 jr z,retry ; Yes, then retry once more\r
326\r
327hard$error:\r
328 ; otherwise,\r
329 xor a\r
330 ld (residual),a\r
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
341 ret\r
342\r
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
376u$conin$echo:\r
377\r
378 call ?const\r
379 or a\r
380 jr z,u$c1 ; see if any char already struck\r
381 call ?conin\r
382 jr u$conin$echo ; yes, eat it and try again\r
383u$c1:\r
384 call ?conin\r
385 push af\r
386 ld c,a\r
387 cp ' '-1\r
388 call nc,?cono\r
389 pop af\r
390 cp 'a'\r
391 ret c\r
392 sub 'a'-'A' ; make upper case\r
393 ret\r
394\r
395\r
396residual:\r
397 db 0\r
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
404 ; -read/write- -login-\r
405 ds 2 ; @trk xdph address\r
406 ds 2 ; @sect (3 byte)\r
407 ds 1 ; @cnt\r
408 ds 3 ; transfer addr\r
409send_msg_rw_len equ $ - send_msg\r
410send_msg_login_len equ 7\r
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
428 db ', Read, ',0\r
429write$msg:\r
430 db ', Write, ',0\r
431\r
432 ; general driver errors\r
433\r
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
438drvmsg4: db 'Access beyond disk size, ',0\r
439drvmsg5: db 'Write protected, ',0\r
440drvmsg6: db 'No media, ',0\r
441drvmsg_size equ $ - drvmsg0\r
442drvmsg_count equ 7\r
443\r
444 ; fat file system errors\r
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
467fr$msg$size equ $ - fr$msg0\r
468fr$msg$count equ 21\r
469\r
470 end\r