]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blame - cbios/cfio.180
Reverse local stack patch for sdio/cfio
[z180-stamp-cpm3.git] / cbios / cfio.180
CommitLineData
4fc939ea
L
1 TITLE 'compactflash 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 cf0,cf1,cf2,cf3\r
9\r
10 ; Variables containing parameters passed by BDOS\r
11\r
12 extrn @xdph\r
13 extrn @adrv,@rdrv\r
14 extrn @trk,@sect,@cnt\r
aeb747d4 15 extrn @dma,@dbnk\r
4fc939ea
L
16\r
17 ; System Control Block variables\r
18\r
19 extrn @ermde ; BDOS error mode\r
20\r
aeb747d4 21 ; Utility routines\r
4fc939ea
L
22\r
23 extrn ?wboot ; warm boot vector\r
aeb747d4
L
24 extrn ?pmsg ; print message @<HL>\r
25 extrn pr.idx ; print indexed message\r
26 extrn pr.inln ; print inline message\r
27 extrn pr.decl ; print 32 bit decimal number\r
28 extrn pr.errors ; print BIOS disk error header\r
29 extrn ?cono ; console out\r
30 extrn bnk2phy ; translate banked to physical linear address\r
31 extrn add_hla ; add <A> to <HL>\r
1e1efaf4 32 extrn gstimer ; get timer short (16 bit)\r
4fc939ea
L
33\r
34 ; Port Address Equates\r
35\r
36 include config.inc\r
37 include z180reg.inc\r
38\r
39 ; CP/M 3 Disk definition macros\r
40\r
41 maclib cpm3slr.lib\r
42\r
43 ; Z180 macro library instruction definitions (ignored by slr180)\r
44\r
45 include z180.lib\r
46\r
47DEBUG equ false ; not used\r
48MULTIIO equ true ; Multi I/O currently not fully implemented.\r
49\r
50 ; IDE Task File Register Definitions\r
51\r
52;IdeDOR equ IDEBASE+6 ; Digital Output Register\r
53IDEDat equ IDEBASE+0 ; Data Register\r
54IDEErr equ IDEBASE+1 ; Error Register\r
55IDEFeat equ IDEBASE+1 ; Feature Register\r
56IDESCnt equ IDEBASE+2 ; Sector Count\r
57IDESNum equ IDEBASE+3 ; Sector Number\r
58IDECLo equ IDEBASE+4 ; Cylinder Low\r
59IDECHi equ IDEBASE+5 ; Cylinder High\r
60IDESDH equ IDEBASE+6 ; Drive and Head\r
61IDECmd equ IDEBASE+7 ; Command / Status\r
62\r
63 ; IDE Hard disk commands:\r
64\r
65CmdHome equ 10h ; Recalibrate\r
66CmdRd equ 20h ; Read Sector\r
67CmdWr equ 30h ; Write Sector\r
68CmdInit equ 91h ; Initialize Drive Params\r
69CmdId equ 0ECh ; Read ID\r
70CmdSF equ 0EFh ; Set Feature\r
71\r
72 ; Partition Table Structures\r
73\r
74PART_TYPE equ 4\r
75PART_START equ 8\r
76PART_SIZE equ 12\r
77\r
78 ; Partition table id\r
79 ; (see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html)\r
80\r
81PARTID1_FAT16 equ 00EH\r
82PARTID2_FAT16 equ 006H\r
83PARTID_CPM equ 052H\r
84\r
85MAXDISKS equ 4\r
86\r
87; parttabl fields\r
88PTAB_TYPE equ 0 ; 1 byte\r
89PTAB_START equ 1 ; 4 byte (28 bit, max 128 GiB)\r
90PTAB_SIZE equ 5 ; 4 byte (3 needed, 20 bit, max 512 MiB)\r
91PTAB_SPT equ 9 ; 1 byte\r
92PTAB_BSH equ 10 ; 1 byte\r
93\r
94PARTENTRY_SIZE equ 11\r
95\r
96\r
97 ; common control characters\r
98\r
99cr equ 13\r
100lf equ 10\r
101bell equ 7\r
102\r
103;-------------------------------------------------------------------------------\r
104\r
105 ; Macro: wait while device is busy\r
106\r
107WAITNOTBUSY macro\r
108 local wait\r
109wait: in a,(IdeCmd)\r
110 rla\r
111 jr c,wait\r
112 endm\r
113\r
1e1efaf4 114 ; Macro: wait until device is ready\r
4fc939ea
L
115\r
116WAITREADY macro\r
117 local wait\r
118wait: in a,(IdeCmd)\r
119 xor 01000000b\r
120 and 11000000b\r
121 jr nz,wait\r
122 endm\r
123\r
124 ; Macro: wait for DRQ signal\r
125\r
126WAITDRQ macro\r
127 local wait\r
128wait: in a,(IdeCmd)\r
129 bit 3,a\r
130 jr z,wait\r
131 endm\r
132\r
133;-------------------------------------------------------------------------------\r
134\r
135 dseg\r
136\r
137 ; Extended Disk Parameter Headers (XPDHs)\r
138\r
139 ; dph translate$table, - disk parameter header\r
140 ; disk$parameter$block,\r
141 ; checksum$size, (optional)\r
142 ; alloc$size (optional)\r
143\r
144 dw cf$write\r
145 dw cf$read\r
146 dw cf$login\r
147 dw cf$init0\r
148 db 0,0 ; relative drive zero\r
149cf0: dph 0,dpbsimhd512,0\r
150\r
151 dw cf$write\r
152 dw cf$read\r
153 dw cf$login\r
154 dw cf$init1\r
155 db 1,0 ; relative drive one\r
156cf1: dph 0,dpbsimhd512,0\r
157\r
158 dw cf$write\r
159 dw cf$read\r
160 dw cf$login\r
161 dw cf$init2\r
162 db 2,0 ; relative drive zero\r
163cf2: dph 0,dpbsimhd512,0\r
164\r
165 dw cf$write\r
166 dw cf$read\r
167 dw cf$login\r
168 dw cf$init3\r
169 db 3,0 ; relative drive one\r
170cf3: dph 0,dpbsimhd512,0\r
171\r
172 cseg ; DPB must be resident\r
173\r
174 ; dpb physical$sector$size, - disk parameter block\r
175 ; physical$sectors$per$track,\r
176 ; number$tracks,\r
177 ; block$size,\r
178 ; number$dir$entries,\r
179 ; track$offset,\r
180 ; checksum$vec$size (optional)\r
181\r
182dpbsimhd512:\r
183 dpb 512,8,2048,4096,1024,6,8000h\r
184\r
185;-------------------------------------------------------------------------------\r
186\r
187 dseg ; rest is banked\r
188\r
189; Disk I/O routines for standardized BIOS interface\r
190\r
191; Initialization entry point.\r
192; called for first time initialization.\r
193\r
194cf$init0:\r
195 call pr.inln ;\r
2fe29e36 196 db 'cfio: CompactFlash Memory Card driver',0\r
4fc939ea
L
197\r
198 ld hl,parttbl ; Clear partition table\r
199 ld b,PARTENTRY_SIZE*MAXDISKS\r
200ini_clrtbl:\r
201 ld (hl),0\r
202 inc hl\r
203 djnz ini_clrtbl\r
204\r
205 call cf_init ; init ide interface / cf card\r
2fe29e36 206 jr nz,nocard\r
4fc939ea 207 call ident_read ; identify drive\r
2fe29e36 208 jr nz,nocard\r
4fc939ea
L
209\r
210 call prnt_info ; print device information\r
211 call ptab_read ; read the partition table\r
2fe29e36 212 jr nz,pend\r
4fc939ea
L
213\r
214 ld c,0 ; number of found disks (paritions)\r
215 jr nz,pend\r
216\r
217 ld hl,tmpsecbuf+512-1 ; Point to first byte of partition table\r
218 ld a,(hl) ; Test, if it has a valid MBR\r
219 cp 0AAH ;\r
220 jr nz,pend ;\r
221 dec hl\r
222 ld a,(hl) ;\r
223 cp 055H ;\r
224 jr nz,pend ;\r
225\r
226 ; Search for valid Partitions\r
227\r
228 ld hl,tmpsecbuf+512-2-64+PART_TYPE ; Point to partition type of first first partition table entry\r
229 ld de,parttbl ;\r
230 ld b,4 ; Max # of partition table entries\r
231ploop:\r
232 ld a,(hl) ; Get Partitiontype\r
233 cp PARTID_CPM ; Test for CP/M Partition\r
234 ld a,16 ; Offset to next entry\r
235 jr nz,nextp\r
236 push bc\r
237 ld a,(hl) ; (Re)get Partitiontype\r
238 ld (de),a ; Save paritition type\r
239 inc de\r
240 inc hl ; Point to partition start (lba)\r
241 inc hl\r
242 inc hl\r
243 inc hl\r
244 ld bc,8 ; Copy partition start and size\r
245 ldir\r
246 rept PARTENTRY_SIZE-8-1\r
247 inc de\r
248 endm\r
249 pop bc\r
250 inc c ; One more found\r
251 ld a,c\r
252 cp MAXDISKS\r
253 jr z,pend\r
254 ld a,4\r
255nextp:\r
256 call add_hla\r
257 djnz ploop\r
258pend:\r
259 ;TODO: variable disk format: sectors per track, ...\r
260\r
261 call prnt_ptab ; Print partition table info\r
262 ret\r
263\r
2fe29e36
L
264nocard:\r
265 call pr.inln\r
266 db ": No Card",cr,lf,0\r
267 ret\r
268\r
4fc939ea
L
269\r
270cf$init1:\r
271cf$init2:\r
272cf$init3:\r
273 ret ; all initialization done by drive 0\r
274\r
275; Read ID from Hard Disk\r
276\r
277ident_read:\r
278 WAITREADY\r
279 ld a,0E0h ; assume unit 0,\r
280 out (IdeSDH),a ;\r
281 ld a,CmdId\r
282 out (IdeCmd),a ; command: read sector data\r
283 ld hl,tmpsecbuf\r
284 ld bc,IdeDat ; B = 0 (counter), C = I/O address\r
285 WAITDRQ ; wait for DRQ to become active\r
286 inir\r
287 inir ; read 512 data bytes (2 x 256)\r
288 WAITNOTBUSY\r
289 in a,(IdeCmd) ; check final drive status\r
290 and 10001001b ; Busy, DRQ, or Error?\r
291 ret z ; no: everything is ok\r
292 ld a,1 ; return with A=1 on error\r
293 ret\r
294\r
295\r
296; Read partition table\r
297\r
298ptab_read:\r
299 WAITREADY\r
300 ld a,0E0h ; assume unit 0, lba mode\r
301 out (IdeSDH),a ;\r
302 xor a ; sector 0 (lba)\r
303 out (IdeSNum),a ;\r
304 out (IdeCLo),a\r
305 out (IdeCHi),a ;\r
306 inc a ; one sector to read\r
307 out (IdeSCnt),a ; set sector count\r
308\r
309 ld a,CmdRd\r
310 out (IdeCmd),a ; command: read sector data\r
311 ld hl,tmpsecbuf\r
312 ld bc,IdeDat ; B = 0 (counter), C = I/O address\r
313 WAITDRQ ; wait for DRQ to become active\r
314 inir\r
315 inir ; read 512 data bytes (2 x 256)\r
316 WAITNOTBUSY\r
317 in a,(IdeCmd) ; check final drive status\r
318 and 10001001b ; Busy, DRQ, or Error?\r
319 ret z ; no: everything is ok\r
320 ld a,1 ; return with A=1 on error\r
321 ret\r
322\r
323cf_init:\r
1f1b7dfa
L
324 ld hl,25600 ; 32000/1.25 ms\r
325 call wait_nbsy_to ; wait for BSY == 0\r
1e1efaf4 326 jr c,cfi_error ; return error on timeout\r
1f1b7dfa
L
327\r
328 ld hl,25600 ; 32000/1.25 ms\r
329 call wait_rdy_to ; wait for RDY == 1\r
1e1efaf4
L
330 jr c,cfi_error ; return error on timeout\r
331\r
4fc939ea
L
332 ld a,0E0h ; assume unit 0, lba mode\r
333 out (IdeSDH),a ;\r
1f1b7dfa
L
334\r
335 xor a ; execute NOP command\r
336 out (IdeCmd),a ;\r
337 ld hl,100\r
338 call wait_rdy_to\r
339 jr c,cfi_error\r
340 and 11111001b ;\r
341 cp 01010001b ; should return error\r
342 jr nz,cfi_error ;\r
343 ld a,10h ; execute RECALIBRATE command\r
344 out (IdeCmd),a ;\r
345 ld hl,100\r
346 call wait_rdy_to\r
347 and 11111001b ;\r
348 cp 01010000b ; should return ok\r
349 jr nz,cfi_error ;\r
350\r
4fc939ea
L
351 ld a,1 ; Enable 8-bit data transfer.\r
352 out (IDEFeat),a\r
1e1efaf4
L
353 ld a,CmdSF ; Set feature command\r
354 out (IdeCmd),a ;\r
4fc939ea
L
355 WAITNOTBUSY\r
356 in a,(IdeCmd) ; check final drive status\r
357 and 10001001b ; Busy, DRQ, or Error?\r
358 ret z ; no: everything is ok\r
1e1efaf4 359cfi_error:\r
4fc939ea
L
360 ld a,1 ; return with A=1 on error\r
361 ret\r
362\r
aeb747d4
L
363;-------------------------------------------------------------------------------\r
364; print char, skipping leading blanks\r
4fc939ea
L
365\r
366pr_char_nlbl:\r
367 bit 0,b\r
368 jr z,pr_char\r
369 cp ' '\r
370 ret z\r
371 res 0,b\r
372 ; fall thru\r
aeb747d4
L
373\r
374; print character, saving hl, de, bc\r
375\r
4fc939ea
L
376pr_char:\r
377 push hl\r
378 push de\r
379 push bc\r
380 ld c,a\r
381 call ?cono\r
382 pop bc\r
383 pop de\r
384 pop hl\r
385 ret\r
386\r
1e1efaf4
L
387;-------------------------------------------------------------------------------\r
388\r
389reftime:dw 2\r
390to: dw 2\r
391\r
392chk_to:\r
393 or a\r
394 jr z,chk_1\r
395 ld (to),hl\r
396 ld hl,0\r
397 call gstimer\r
398 ld (reftime),hl\r
399 ret\r
400chk_1:\r
401 push hl\r
402 push de\r
403 ld hl,(reftime)\r
404 call gstimer\r
405 ex de,hl\r
406 ld hl,(to)\r
407 or a\r
408 sbc hl,de\r
409 pop de\r
410 pop hl\r
411 ret\r
412\r
413\r
414; Wait while device is busy with time out\r
415; hl: timer tics (1.25ms) to wait\r
1f1b7dfa
L
416; return:\r
417; a: IDE status register\r
418; carry flag set, if time out\r
1e1efaf4
L
419\r
420wait_nbsy_to:\r
421 ld a,1\r
422 call chk_to\r
423wnb_l:\r
424 in a,(IdeCmd)\r
425 rla\r
426 jr nc,wnb_e\r
427 xor a\r
428 call chk_to\r
429 jr nc,wnb_l\r
430wnb_e:\r
1f1b7dfa 431 in a,(IdeCmd)\r
1e1efaf4
L
432 ret\r
433\r
434; Wait for ready signal with time out\r
435; hl: timer tics (1.25ms) to wait\r
1f1b7dfa
L
436; return:\r
437; a: IDE status register\r
438; carry flag set, if time out\r
1e1efaf4
L
439\r
440wait_rdy_to:\r
441 ld a,1\r
442 call chk_to\r
443wrdy_l:\r
444 in a,(IdeCmd)\r
445 xor 01000000b\r
446 and 11000000b ; clears carry\r
447 jr z,wrdy_e\r
448 xor a\r
449 call chk_to\r
450 jr nc,wrdy_l\r
451wrdy_e:\r
1f1b7dfa 452 in a,(IdeCmd)\r
1e1efaf4
L
453 ret\r
454\r
455;-------------------------------------------------------------------------------\r
456\r
4fc939ea
L
457; Print an id string\r
458; Remove leading and trailing spaces\r
459\r
460pr_id:\r
461 push hl ; Save string address\r
462 ld b,0\r
463 add hl,bc\r
464 dec hl ; Point to last char.\r
465 ld a,' '\r
466prn_el: ; Reduce string len by number of trailing spaces\r
467 dec hl\r
468 cpi\r
469 jr nz,prn_el1 ; No more spaces\r
470 jp po,prn_el2 ; No more characters\r
471 cpd\r
472 dec hl\r
473 jr nz,prn_el1\r
474 jp po,prn_el2\r
475 jr prn_el\r
476prn_el1:\r
477 inc c\r
478prn_el2:\r
479 pop hl ; Restore beginning of string\r
480 ld a,c\r
481 or a ; Test number of remaining chars\r
482 ret z ; Done, if string was spaces only\r
483\r
484 ld b,1 ; Flag, skip spaces\r
485prn_lp:\r
486 inc hl ;Text is low byte high byte format\r
487 ld a,(hl)\r
488 call pr_char_nlbl\r
489 dec c\r
490 ret z\r
491 dec hl\r
492prn_lp1:\r
493 ld a,(hl)\r
494 call pr_char_nlbl\r
495 dec c\r
496 ret z\r
497 inc hl\r
498 inc hl\r
499 jr prn_lp\r
500\r
501; Print divice information\r
502\r
503prnt_info:\r
504 call pr.inln\r
2fe29e36 505 db cr,lf,' Model: ',0\r
4fc939ea
L
506 ld hl,tmpsecbuf + 27*2 ; Model number\r
507 ld c,20*2 ; max character count\r
508 call pr_id ;\r
509 call pr.inln\r
510 db ', S/N: ',0\r
511 ld hl,tmpsecbuf + 10*2 ; Serial number\r
512 ld c, 10*2\r
513 call pr_id\r
514 call pr.inln\r
515 db ', Rev: ',0\r
516 ld hl,tmpsecbuf + 23*2 ; Firmware revision\r
517 ld c, 4*2\r
518 call pr_id\r
519\r
520 call pr.inln\r
521 db cr,lf,' Size: ',0\r
522 ld hl,(tmpsecbuf+60*2) ;Total Sectors Addressable in LBA Mode\r
523 ld de,(tmpsecbuf+61*2) ;\r
524 push hl\r
525 push de\r
526 ld bc,1\r
527 call pr.decl\r
528 call pr.inln\r
529 db ' Sectors (',0\r
530 pop de\r
531 pop hl\r
532 srl d\r
533 rr e\r
534 rr h\r
535 rr l\r
536 ld bc,1\r
537 call pr.decl\r
538 call pr.inln\r
539 db ' KiB)',cr,lf,0\r
540 ret\r
541\r
542; Print partition table info\r
543\r
544prnt_ptab:\r
545 ld ix,parttbl\r
546 ld c,0\r
547prp_lp:\r
548 ld a,c\r
549 cp 4\r
550 ret z\r
551 ld a,(ix+PTAB_TYPE)\r
552 or a\r
553 ret z\r
554\r
555 push bc\r
556 call pr.inln\r
557 db ' ',0\r
558 ld a,(@adrv)\r
559 add a,c\r
560 add a,'A'\r
561 call pr_char\r
562 call pr.inln\r
563 db ': CP/M partition at: ',0\r
564 ld l,(ix+PTAB_START+0)\r
565 ld h,(ix+PTAB_START+1)\r
566 ld e,(ix+PTAB_START+2)\r
567 ld d,(ix+PTAB_START+3)\r
568 ld bc,1\r
569 call pr.decl\r
570 call pr.inln\r
571 db ', size: ',0\r
572 ld l,(ix+PTAB_SIZE+0)\r
573 ld h,(ix+PTAB_SIZE+1)\r
574 ld e,(ix+PTAB_SIZE+2)\r
575 ld d,(ix+PTAB_SIZE+3)\r
576 srl d\r
577 rr e\r
578 rr h\r
579 rr l\r
580 ld bc,1\r
581 call pr.decl\r
582 call pr.inln\r
583 db 'KiB',cr,lf,0\r
584 ld bc,PARTENTRY_SIZE\r
585 add ix,bc\r
586 pop bc\r
587 inc c\r
588 jr prp_lp\r
589\r
590;-------------------------------------------------------------------------------\r
591\r
592; This entry is called when a logical drive is about to\r
593; be logged into for the purpose of density determination.\r
594; It may adjust the parameters contained in the disk\r
595; parameter header pointed at by <DE>\r
596;\r
597; absolute drive number in @adrv (8 bits) +0\r
598; relative drive number in @rdrv (8 bits) +1\r
599\r
600cf$login:\r
601 xor a\r
602 ld (residual),a ; just in case\r
603\r
604 ld hl,parttbl\r
605 ld a,(@rdrv)\r
606 ld e,a\r
607 ld d,PARTENTRY_SIZE\r
608 mlt de\r
609 add hl,de\r
610 ld a,(hl)\r
611 or a\r
612 ret nz\r
613 ld hl,0\r
614 ld (@xdph),hl\r
615 ret ;\r
616\r
617; disk READ and WRITE entry points.\r
618; these entries are called with the following arguments:\r
619;\r
aeb747d4
L
620; operation type (r/w) in @op (8 bits) +0\r
621; absolute drive number in @adrv (8 bits) +1\r
622; relative drive number in @rdrv (8 bits) +2\r
623; disk track address in @trk (16 bits) +3\r
624; disk sector address in @sect(16 bits) +5\r
625; multi sector count in @cnt (8 bits) +7\r
626; disk transfer address in @dma (16 bits) +8\r
627; disk transfer bank in @dbnk (8 bits) +10\r
4fc939ea
L
628; pointer to XDPH in <DE>\r
629;\r
630; they transfer the appropriate data, perform retries\r
631; if necessary, then return an error code in <A>\r
632\r
633cf$read:\r
4fc939ea
L
634 ld bc,M_DIM1*256 + CmdRd ; Transfermode: i/o to memory++\r
635 jr rw$common\r
636cf$write:\r
4fc939ea
L
637 ld bc,0*256 + CmdWr ; Transfermode: memory++ to i/o\r
638rw$common:\r
639\r
640 if MULTIIO\r
641 ld hl,residual ; remainng sectors from last multi io?\r
642 ld a,(hl)\r
643 sub a,1\r
644 jr c,rwc_new_sectors\r
645\r
646 ld (hl),a\r
647 xor a\r
648 ret\r
649 endif\r
650\r
651rwc_new_sectors:\r
4fc939ea
L
652 in0 a,(dcntl)\r
653 and a,~(M_DMS1+M_DIM1+M_DIM0)\r
654 or b\r
655 out0 (dcntl),a\r
656\r
657 ld b,1 ; assume 1 sector to transfer\r
658 if MULTIIO\r
659 ld a,(@cnt)\r
660 or a\r
661 jr z,rwc_doit\r
662\r
663 ld b,a ; number of sectors to transfer\r
664 dec a ; save remaining\r
665 ld (hl),a\r
666 xor a ; reset multi sector count\r
667 ld (@cnt),a\r
668rwc_doit:\r
669 endif\r
670\r
671 ld iy,parttbl\r
672 ld a,(@rdrv)\r
673 ld e,a\r
674 ld d,PARTENTRY_SIZE\r
675 mlt de\r
676 add iy,de\r
677\r
678retry:\r
679 ld a,b\r
680 out (IdeSCnt),a ; set sector count\r
681\r
682; compute logical block number (lba) --> cf-controller\r
683\r
684 ; TODO: sectors per track from dpb\r
685 ; lba = track * 8 + sector\r
686\r
687 xor a\r
688 ld hl,(@trk)\r
689 add hl,hl\r
690 adc a,a ; *2\r
691 add hl,hl\r
692 adc a,a ; *4\r
693 add hl,hl\r
694 adc a,a ; *8\r
695 ld de,(@sect)\r
696 add hl,de\r
697 adc a,0\r
698\r
699 push hl ; check, if block# fits in partition\r
700 ld e,(iy+PTAB_SIZE+0)\r
701 ld d,(iy+PTAB_SIZE+1)\r
702 sbc hl,de\r
1f1b7dfa 703 ld e,a\r
4fc939ea 704 sbc a,(iy+PTAB_SIZE+2)\r
4fc939ea
L
705 pop hl\r
706 jr c,lba_ok\r
707 ld a,1 ; block# >= partition size, return error\r
8d7aab73 708 ret\r
4fc939ea
L
709\r
710lba_ok:\r
711 WAITREADY\r
1f1b7dfa 712 ld a,(iy+PTAB_START+0) ; add partition start\r
4fc939ea
L
713 add a,l\r
714 out (IdeSNum),a\r
715 ld a,(iy+PTAB_START+1)\r
716 adc a,h\r
717 out (IdeCLo),a\r
718 ld a,(iy+PTAB_START+2)\r
719 adc a,e\r
720 out (IdeCHi),a\r
721 ld a,(iy+PTAB_START+3)\r
722 adc a,0\r
723 and 00FH\r
724 or 0E0H\r
725 out (IdeSDH),a\r
726\r
727 ld hl,(@dma)\r
728 ld a,(@dbnk)\r
729\r
730; compute pysical transfer address --> DMA\r
731\r
732 call bnk2phy ; phys. linear address\r
733 out0 mar1l,l\r
734 out0 mar1h,h\r
735 out0 mar1b,a\r
736 ld a,IdeDat\r
737 out0 iar1l,a\r
738 xor a\r
739 out0 iar1h,a\r
740 out0 iar1b,a\r
741 out0 bcr1l,a\r
742 ld a,c\r
743 out (IDECmd),a\r
744 push bc\r
745nxt_sec:\r
746 ld a,2\r
747 out0 bcr1h,a\r
748 WAITDRQ\r
749 ld a,M_DE1+M_NDWE0\r
750 out0 (dstat),a\r
751wait_dma:\r
752 in0 a,(dstat)\r
753 bit DE1,A\r
754 jr nz,wait_dma\r
755\r
756 WAITNOTBUSY\r
757 in a,(IdeCmd) ; check final drive status\r
758 bit 0,a ; any error?\r
759 jr nz,err_out\r
760 djnz nxt_sec\r
761err_out:\r
762 pop bc\r
763 ld e,a\r
764 and 10001001b ; Busy, DRQ, or Error?\r
8d7aab73 765 ret z ; Return to BDOS if no error\r
4fc939ea 766\r
aeb747d4
L
767 ld hl,print_details\r
768 call pr.errors\r
769 jp z,retry ; Yes, then retry once more\r
770 ; otherwise,\r
771 xor a\r
772 ld (residual),a\r
4fc939ea 773\r
aeb747d4
L
774 ld a,1 ; return hard error to BDOS\r
775 ret\r
4fc939ea 776\r
aeb747d4 777;-------------------------------------------------------------------------------\r
4fc939ea 778\r
aeb747d4 779print_details:\r
4fc939ea
L
780 ld hl,msg$drq\r
781 bit 3,e\r
782 call nz,?pmsg\r
783\r
784 bit 0,e\r
aeb747d4 785 ret z\r
4fc939ea
L
786\r
787 in a,(IDEErr)\r
aeb747d4 788 ld e,8\r
4fc939ea 789errm1:\r
aeb747d4
L
790 ld hl,b0$msg ; point at message[0]\r
791 dec e ; index of next message\r
792 add a,a ; shift left and push residual bits with status\r
4fc939ea 793 push af\r
aeb747d4
L
794 ld a,e\r
795 call c,pr.idx ; print it, if bit is set.\r
4fc939ea 796 pop af\r
aeb747d4 797 jr nz,errm1 ; if any more bits left, continue\r
4fc939ea
L
798 ret\r
799\r
aeb747d4
L
800;-------------------------------------------------------------------------------\r
801; error message components\r
4fc939ea 802\r
4fc939ea
L
803msg$drq:\r
804 db 'DRQ, ',0\r
4fc939ea 805\r
aeb747d4
L
806b7$msg: db ' Bad Block detected,',0\r
807b6$msg: db ' Uncorrectable Data Error,',0\r
808b5$msg: db ' Media Changed,',0\r
809b4$msg: db ' Sector ID Not Found,',0\r
810b3$msg: db ' Media Change Requst,',0\r
811b2$msg: db ' Aborted Command,',0\r
812b1$msg: db ' Track 0 Not Found,',0\r
813b0$msg: db ' AM Not Found (or general error),',0\r
814 db 0\r
815\r
816;-------------------------------------------------------------------------------\r
4fc939ea
L
817\r
818residual:\r
819 db 0\r
820\r
821parttbl:\r
822 ds PARTENTRY_SIZE*MAXDISKS\r
823\r
824tmpsecbuf: ;temporary sector buffer\r
825 ds 512\r
826\r
827 end\r