]> cloudbase.mooo.com Git - avrcpm.git/blob - dsk_fsys.asm
* avr/dsk_fat16.asm
[avrcpm.git] / dsk_fsys.asm
1 ; Filesystem functions for the Interaction with BIOS and Disks
2 ;
3 ; Copyright (C) 2010 Frank Zoll
4 ;
5 ; This file is part of avrcpm.
6 ;
7 ; avrcpm is free software: you can redistribute it and/or modify it
8 ; under the terms of the GNU General Public License as published by
9 ; the Free Software Foundation, either version 3 of the License, or
10 ; (at your option) any later version.
11 ;
12 ; avrcpm is distributed in the hope that it will be useful,
13 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ; GNU General Public License for more details.
16 ;
17 ; You should have received a copy of the GNU General Public License
18 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
19 ;
20 ; $Id$
21 ;
22
23
24 ; ---------------- Defines for the Filesystem Interface -------
25
26 ;*****************************************************
27 ;* Disk-Manager constants *
28 ;*****************************************************
29 .equ dskType_None = 0
30 .equ dskType_CPM = 1
31 .equ dskType_FAT = 2
32 .equ dskType_RAM = 3
33
34 ;*****************************************************
35 ;* CP/M to host disk constants *
36 ;*****************************************************
37 .equ MAXDISKS = 6 ;Max number of Disks (partitions)
38 .equ PARTENTRY_SIZE = 9 ;Size of a Partitiontableentry
39 .equ blksize = 1024 ;CP/M allocation size
40 .equ hostsize = 512 ;host disk sector size
41 ; .equ hostspt = 20 ;host disk sectors/trk
42 .equ hostblk = hostsize/128 ;CP/M sects/host buff
43 ; .equ CPMSPT = hostblk*hostspt ;CP/M sectors/track
44 .equ CPMSPT = 26 ;
45 .equ SECMSK = hostblk-1 ;sector mask
46 .equ SECSHF = log2(hostblk) ;sector shift
47
48 ;*****************************************************
49 ;* BDOS constants on entry to write *
50 ;*****************************************************
51 .equ WRALL = 0 ;write to allocated
52 .equ WRDIR = 1 ;write to directory
53 .equ WRUAL = 2 ;write to unallocated
54 .equ WRTMSK= 3 ;write type mask
55
56 .equ READ_FUNC = 7
57 .equ WRITE_FUNC = 6
58 .equ BOOT_FUNC = 5
59 .equ HOME_FUNC = 4
60
61 ;----------------------------------------------- Start of Data Segment
62
63 .dseg
64
65 ; The following 3 variables are copied from DRAM.
66 ; Don't change order.
67
68 biosdrvtbl: .byte 2 ;
69 biosdirbuf: .byte 2 ;
70 biosenddat: .byte 2 ;
71
72 ndisks: .byte 1 ;Number of CP/M disks
73
74 ; The following 5 variables are accessed from 8080/z80 via the
75 ; virtual port interface. Don't change order.
76
77 biospar_base:
78 bcbadr: .byte 2 ;adr of BiosControlBlock
79 seekdsk: .byte 1 ;seek disk number
80 seektrk: .byte 2 ;seek track number
81 seeksec: .byte 2 ;seek sector number
82 dmaadr: .byte 2 ;last dma address
83
84 unacnt: .byte 1 ;unalloc rec cnt
85 unadsk: .byte 1 ;last unalloc disk
86 unatrk: .byte 2 ;last unalloc track
87 unasec: .byte 1 ;last unalloc sector
88
89 erflag: .byte 1 ;error reporting
90 wrtype: .byte 1 ;write operation type
91
92 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
93 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
94 hostparttbltop:
95 hostdsk: .byte 1 ;host disk number
96 hosttype: .byte 1 ;host disk type (same entry as 1 parition entry)
97 hostlba: .byte 3 ;host sector number (relative to partition start)
98
99
100 ; ------------------------------- Start of Code Segment
101 .cseg
102
103 ; ====================================================================
104 ; Function: Virtual Port Interface
105 ; ====================================================================
106 ; Parameters
107 ; --------------------------------------------------------------------
108 ; Registers :
109 ; Variables :
110 ;
111 ; --------------------------------------------------------------------
112 ; Description:
113 ; ====================================================================
114
115 dsk_param_getadr:
116 ldiw z,biospar_base
117 add zl,temp3
118 adc zh,_0
119 ret
120
121 dsk_param_wr:
122 rcall dsk_param_getadr
123 st z,temp
124 cpi temp3,bcbadr+1-seektrk
125 brne dsk_param_wr1
126 std z+1,_0
127 dsk_param_wr1:
128 cpi temp3,bcbadr+1-biospar_base
129 breq SetBCB
130 ret
131
132 dsk_param_rd:
133 cpi temp3,seekdsk-biospar_base
134 breq dskDiskCheck
135 rcall dsk_param_getadr
136 ld temp,z
137 ret
138
139 dskDiskCheck:
140 lds temp2,seekdsk
141 cpi temp2,RAMDISKNR
142 brsh dsk_dchrd ;maybe ramdisk
143
144 ; Check if selected disk # is less then # of disks.
145
146 lds temp,ndisks
147 tst temp ;0 disks?
148 brne dsk_dchpart1
149
150 ; No disks yet, need to init
151
152 rcall mgr_init_partitions ;disk chanched?
153 sbrs temp,7
154 rjmp dsk_dchpart0
155 push temp
156 rcall dsk_drvtblinit
157 rcall dbg_prdrvtbl
158 pop temp
159 dsk_dchpart0:
160 cbr temp,0x80
161 lds temp2,seekdsk
162
163 dsk_dchpart1:
164 cp temp2,temp
165 brsh dsk_dcher
166
167 printnewline
168 printstring "Select: "
169 mov temp,temp2
170 rcall printhex
171
172 lds xl,biosdrvtbl
173 lds xh,biosdrvtbl+1
174 lsl temp2 ;drive #
175 add xl,temp2
176 adc xh,_0
177 rcall dram_readw_pp
178
179 printstring ", "
180 rcall printhexw
181
182 or temp,temp2
183 brne dsk_dchend
184 lds temp,seekdsk
185 rcall dsk_diskinit
186 brne dsk_dcher
187
188 dsk_dchend:
189 ldi temp,0
190 ret
191
192 dsk_dchrd:
193 #if RAMDISKCNT
194 cpi temp,RAMDISKNR+RAMDISKCNT
195 brlo dsk_dchend
196 #endif
197 dsk_dcher:
198 ldi temp,0xff ;error return
199 ret
200
201 dskErrorRet:
202 lds temp,erflag
203 ret
204
205 SetBCB:
206 lds xl,bcbadr
207 mov xh,temp
208 ldiw z,biosdrvtbl
209 ldi temp3,6
210 sbcb_l:
211 rcall dram_read_pp
212 st z+,temp
213 dec temp3
214 brne sbcb_l
215
216 rcall dbg_print_biosd
217 rcall dsk_drvtblinit
218
219 ret
220
221 ;---------------------------------------------------------------------
222
223 dbg_prdrvtbl:
224 push xh
225 push xl
226 push temp3
227 push temp2
228 push temp
229 printnewline
230 printstring "drvtbl ("
231 lds xl,biosdrvtbl
232 lds xh,biosdrvtbl+1
233 movw temp,x
234 rcall printhexw
235 printstring "): "
236 ldi temp3,16
237 dbg_pcpel:
238 rcall dram_readw_pp
239 rcall printhexw
240 printstring " "
241 dec temp3
242 brne dbg_pcpel
243 pop temp
244 pop temp2
245 pop temp3
246 pop xl
247 pop xh
248 ret
249
250 ; -------------------------------------------------------------------
251 dbg_print_biosd:
252 printnewline
253 lds temp,bcbadr
254 lds temp2,bcbadr+1
255 rcall printhexw
256 printstring " "
257 lds temp,biosdrvtbl
258 lds temp2,biosdrvtbl+1
259 rcall printhexw
260 printstring " "
261 lds temp,biosdirbuf
262 lds temp2,biosdirbuf+1
263 rcall printhexw
264 printstring " "
265 lds temp,biosenddat
266 lds temp2,biosenddat+1
267 rcall printhexw
268 printstring " "
269
270 ret
271
272
273 ; -------------------------------------------------------------------
274
275
276 .dseg
277 tmpdpb: .byte 15
278
279 .cseg
280
281 ; init bios disk tables.
282 ; leave drive 'A' out for now
283
284
285 rcall dbg_prdrvtbl
286
287 rcall dsk_drvtblinit
288 rcall dbg_prdrvtbl
289
290 lds temp,biosenddat
291 lds temp2,biosenddat+1
292 rcall heap_init
293
294 ldi temp,1
295 dsk_pdil:
296 cp temp,temp2
297 brsh dsk_pdie
298 push temp2
299 push temp
300 rcall dsk_diskinit
301 pop temp
302 pop temp2
303 inc temp
304 rjmp dsk_pdil
305
306
307
308 dsk_pdie:
309 mov temp,temp2
310 ; Test DPBs (avrcpm format)
311
312 dpblist:
313 ;dpb243
314 .db 0x1A,0x00 ;spt
315 .db 0x03,0x07 ;block shift, bock mask
316 .db 0x00,0xF2 ;extent mask, low(disk size -1),
317 .db 0x00,0x3F ;high(disk size -1), low(dir max)
318 .db 0x00,0xC0 ;high(dir max), alloc0
319 .db 0x00,0x10 ;alloc1, low(chk size)
320 .db 0x00,0x02 ;high(chk size), low(offset)
321 .db 0x00,0x00 ;high(offset), fill
322 ;dpb243
323 .db 0x1A,0x00 ;spt
324 .db 0x03,0x07 ;block shift, bock mask
325 .db 0x00,0xF2 ;extent mask, low(disk size -1),
326 .db 0x00,0x3F ;high(disk size -1), low(dir max)
327 .db 0x00,0xC0 ;high(dir max), alloc0
328 .db 0x00,0x10 ;alloc1, low(chk size)
329 .db 0x00,0x02 ;high(chk size), low(offset)
330 .db 0x00,0x00 ;high(offset), fill
331 ;dpb243
332 .db 0x1A,0x00 ;spt
333 .db 0x03,0x07 ;block shift, bock mask
334 .db 0x00,0xF2 ;extent mask, low(disk size -1),
335 .db 0x00,0x3F ;high(disk size -1), low(dir max)
336 .db 0x00,0xC0 ;high(dir max), alloc0
337 .db 0x00,0x10 ;alloc1, low(chk size)
338 .db 0x00,0x02 ;high(chk size), low(offset)
339 .db 0x00,0x00 ;high(offset), fill
340 ;dpb243
341 .db 0x1A,0x00 ;spt
342 .db 0x03,0x07 ;block shift, bock mask
343 .db 0x00,0xF2 ;extent mask, low(disk size -1),
344 .db 0x00,0x3F ;high(disk size -1), low(dir max)
345 .db 0x00,0xC0 ;high(dir max), alloc0
346 .db 0x00,0x10 ;alloc1, low(chk size)
347 .db 0x00,0x02 ;high(chk size), low(offset)
348 .db 0x00,0x00 ;high(offset), fill
349 #if 0
350 ;rd1016
351 .db 0x20,0x00 ;spt
352 .db 0x04,0x0F ;block shift, bock mask
353 .db 0x00,0xFB ;extent mask, low(disk size -1),
354 .db 0x01,0xBF ;high(disk size -1), low(dir max)
355 .db 0x00,0xE0 ;high(dir max), alloc0
356 .db 0x00,0x30 ;alloc1, low(chk size)
357 .db 0x00,0x02 ;high(chk size), low(offset)
358 .db 0x00,0x00 ;high(offset), fill
359 ;rd9192s
360 .db 0x20,0x00 ;spt
361 .db 0x05,0x1F ;block shift, bock mask
362 .db 0x01,0xFD ;extent mask, low(disk size -1),
363 .db 0x07,0xFF ;high(disk size -1), low(dir max)
364 .db 0x01,0xF0 ;high(dir max), alloc0
365 .db 0x00,0x80 ;alloc1, low(chk size)
366 .db 0x00,0x02 ;high(chk size), low(offset)
367 .db 0x00,0x00 ;high(offset), fill
368 #endif
369
370 ; Test
371 cpy_dpb:
372 push zh
373 push zl
374 push yh
375 push yl
376 ldiw z,dpblist*2
377 ldi temp2,16
378 mul temp,temp2
379 add zl,_tmp0
380 adc zh,_tmp1
381 ldiw y,tmpdpb
382 cpydpb_l:
383 lpm temp,z+
384 st y+,temp
385 cpi yl,low(tmpdpb + 15)
386 brne cpydpb_l
387 pop yl
388 pop yh
389 pop zl
390 pop zh
391 ret
392
393 ; clear drive table
394 ; for now, only entries 1 - 3 are cleared.
395
396 ; ====================================================================
397 ; Function: Clear drive table
398 ; ====================================================================
399 ; Parameters
400 ; --------------------------------------------------------------------
401 ; Registers :
402 ; Variables :
403 ;
404 ; --------------------------------------------------------------------
405 ; Description:
406 ; ====================================================================
407
408 ; For now, only entries 1 - 3 are cleared.
409
410 dsk_drvtblinit:
411 ldsw x,biosdrvtbl
412 adiw x,2
413 ldi temp3,3
414 dsk_drvi_l:
415 ldi temp,0
416 ldi temp2,0
417 rcall dram_writew_pp
418 dec temp3
419 brne dsk_drvi_l
420
421 lds temp,biosenddat
422 lds temp2,biosenddat+1
423 rcall heap_init
424 clr temp
425 ret
426
427
428 ; ----------------------------------------------------------------------
429 ; Init CP/M data structures
430 ; temp = drive #
431 ;
432
433
434 dsk_diskinit:
435 mov temp3,temp ;save disk #
436
437
438 ; Test
439 rcall cpy_dpb
440
441
442
443
444 ; get mem for DPH
445 ; -----------------------------------------------------------------
446 ; DPH: | XLT | | | |DIRBUF | DPB | CSV | ALV |
447 ; -----------------------------------------------------------------
448 ;(offset) 0 2 4 6 8 10 12 14
449
450 ldi temp, low (16)
451 ldi temp2,high(16)
452 rcall heap_get
453 brne dsk_di_1
454 rjmp dsk_di_err ;
455 dsk_di_1:
456 movw x,temp
457 movw y,temp
458 ldi temp,0
459 ldi temp2,0
460 rcall dram_writew_pp ;XLT
461 adiw x,6
462 lds temp,biosdirbuf
463 lds temp2,biosdirbuf+1
464 rcall dram_writew_pp ;DIRBUF
465
466 ; get mem for DPB
467 ; -------------------------------------------------------------
468 ; DPB: | SPT |BSH|BLM|EXM| DSM | DRM |AL0|AL1| CKS | OFF |
469 ; -------------------------------------------------------------
470 ; 0 5 7 11 13
471
472 ldi temp, low (15)
473 ldi temp2,high(15)
474 rcall heap_get
475 breq dsk_di_err_p1
476 movw x,temp
477
478 ldiw z,tmpdpb
479 dsk_dicpl:
480 ld temp,z+
481 rcall dram_write_pp
482 cpi zl,low(tmpdpb + 15)
483 brne dsk_dicpl
484 sbiw x,15
485 movw temp,x
486 movw x,y
487 adiw x,10
488 rcall dram_writew_pp ;DPB
489
490 ; get mem for dir check vector
491
492 lds temp,tmpdpb+11 ;cks
493 lds temp2,tmpdpb+11+1
494 cp temp,_0
495 cpc temp2,_0
496 breq dsk_dicks0
497 rcall heap_get
498 breq dsk_di_err_p1
499 dsk_dicks0:
500 rcall dram_writew_pp ;CSV
501
502 ; get mem for alloc vector
503
504 lds temp,tmpdpb+5 ;dsm
505 lds temp2,tmpdpb+5+1
506 subi temp, low (-8)
507 sbci temp2,high(-8)
508 lsr temp2
509 ror temp
510 lsr temp2
511 ror temp
512 lsr temp2
513 ror temp ;(dsm+1+7)/8
514 rcall heap_get
515 breq dsk_di_err_p1
516 rcall dram_writew_pp ;ALV
517
518 ; success, insert DPH into drvtbl
519
520 lds xl,biosdrvtbl
521 lds xh,biosdrvtbl+1
522 lsl temp3 ;drive #
523 add xl,temp3
524 adc xh,_0
525 movw temp,y
526 rcall dram_writew_pp
527 clr temp
528 ret
529
530 ; error, free mem
531
532 dsk_di_err_p1:
533 movw temp,y
534 rcall heap_release
535 dsk_di_err:
536 ldi temp,1
537 or temp,temp
538 ret
539
540 ; ====================================================================
541 ; Function: Get a Pointer to a Partitiontable entry
542 ; ====================================================================
543 ; Parameters
544 ; --------------------------------------------------------------------
545 ; Registers : [w] z Pointer to the Partitionentry
546 ; [r] xl Number of Diskentry to Read
547 ; [w] _tmp0 scratch
548 ; [w] _tmp1 "
549 ; --------------------------------------------------------------------
550 ; Description:
551 ; ====================================================================
552 dsk_getpartentry:
553
554 ldi zl,PARTENTRY_SIZE
555 mul xl,zl
556 ldiw z,hostparttbl
557 add zl,_tmp0
558 add zh,_tmp1
559 ret
560
561
562 ; ====================================================================
563 ; Function: Does a Disk interaction
564 ; ====================================================================
565 ; Parameters
566 ; --------------------------------------------------------------------
567 ; Registers : none
568 ; Variables : [r] seeksec Sector to read
569 ; [r] seektrk Track to read
570 ; --------------------------------------------------------------------
571 ; Description:
572 ; ====================================================================
573 dskDoIt:
574 .if DISK_DEBUG
575 push temp
576 sbrc temp,READ_FUNC
577 rjmp dskdbgr
578 sbrc temp,WRITE_FUNC
579 rjmp dskdbgw
580 rjmp dskdbge
581
582 dskdbgr:
583 printnewline
584 printstring "Disk read: "
585 rjmp dskdbg1
586 dskdbgw:
587 printnewline
588 printstring "Disk write: "
589 dskdbg1:
590 lds temp,seekdsk
591 subi temp,-('A')
592 rcall uartputc
593 printstring ": track "
594 lds temp2,seektrk+1
595 lds temp,seektrk
596 rcall printhexw
597 printstring ", sector "
598 lds temp,seeksec
599 rcall printhex
600 printstring ", dma-addr "
601 lds temp2,dmaadr+1
602 lds temp,dmaadr
603 rcall printhexw
604 pop temp
605 push temp
606 sbrs temp,WRITE_FUNC
607 rjmp dskdbge
608 printstring " wrtype "
609 andi temp,3
610 rcall printhex
611 dskdbge:
612 pop temp
613 .endif
614 ;See what has to be done.
615 sbrc temp,READ_FUNC
616 rjmp dsk_read
617 sbrc temp,WRITE_FUNC
618 rjmp dsk_write
619 sbrc temp,HOME_FUNC
620 rjmp dsk_home
621 sbrc temp,BOOT_FUNC
622 rjmp dsk_boot
623
624 printstring "DISK I/O: Invalid Function code: "
625 rcall printhex
626 rjmp haltinv
627
628 dsk_boot:
629 sts ndisks,_0 ;no active partitions
630 dsk_cboot:
631 cbi flags,hostact ;host buffer inactive
632 sts unacnt,_0 ;clear unalloc count
633 ret
634
635 dsk_home:
636 sbis flags,hostwrt ;check for pending write
637 cbi flags,hostact ;clear host active flag
638 ret
639
640
641
642 ; ====================================================================
643 ; Function: Does a Disk read operation
644 ; ====================================================================
645 ; Parameters
646 ; --------------------------------------------------------------------
647 ; Registers : in: temp
648 ; Variables : [r] seekdsk Number of Disk to Read
649 ; [r] seeksec Sector to read
650 ; [r] seektrk Track to read
651 ; --------------------------------------------------------------------
652 ; Description:
653 ; ====================================================================
654 dsk_read:
655 sts erflag,_0
656 sbi flags,readop ; Set read operation flag
657
658 ;RAM disk?
659 lds xl,seekdsk
660 #if RAMDISKCNT
661 cpi xl,RAMDISKNR
662 brlt PC+2
663 rjmp rdsk_read
664 #endif
665 rcall dsk_getpartentry ; Get Paritiontableentry
666 ld temp,z ; Get Partitiontype
667
668 ; Isn't it a Disk ?
669 cpi temp,dskType_None
670 brne PC+2
671 rjmp dsk_read_err
672
673 ; It must be a FAT16-Imagefile or CP/M Partition.
674 sts unacnt,_0
675 sbi flags,rsflag ;must read data
676 ldi temp,WRUAL ;write type
677 sts wrtype,temp ;treat as unalloc
678 rjmp dsk_rwoper ;to perform the read
679
680 dsk_read_err:
681 ret
682
683 ; ====================================================================
684 ; Function: Does a Disk write operation
685 ; ====================================================================
686 ; Parameters
687 ; --------------------------------------------------------------------
688 ; Registers : in: temp Write type
689 ; Variables : [r] seekdsk Number of Disk to Read
690 ; [r] seeksec Sector to read
691 ; [r] seektrk Track to read
692 ; --------------------------------------------------------------------
693 ; Description:
694 ; ====================================================================
695 dsk_write:
696 ;write the selected sector
697 sts erflag,_0
698 cbi flags,readop ; not a read operation
699
700 ;RAM disk?
701 lds xl,seekdsk
702 #if RAMDISKCNT
703 cpi xl,RAMDISKNR
704 brlt PC+2
705 rjmp rdsk_write
706 #endif
707 rcall dsk_getpartentry ; Get Paritiontableentry
708 ld temp2,z ; Get Partitiontype
709
710 ; Isn't it a Disk ?
711 cpi temp2,dskType_None
712 brne PC+2
713 rjmp dsk_write_err
714
715 ; It must be a FAT16-Imagefile or CP/M Partition.
716
717 cbi flags,readop ;not a read operation
718
719 andi temp,WRTMSK
720 sts wrtype,temp ;save write type
721
722 cpi temp,WRUAL ;write unallocated?
723 brne dsk_chkuna ;check for unalloc
724
725 ; write to unallocated, set parameters
726 ldi temp,blksize/128 ;next unalloc recs
727 sts unacnt,temp
728 lds temp,seekdsk ;disk to seek
729 sts unadsk,temp ;unadsk = sekdsk
730 lds temp,seektrk
731 sts unatrk,temp ;unatrk = sectrk
732 lds temp,seektrk+1
733 sts unatrk+1,temp ;unatrk = sectrk
734 lds temp,seeksec
735 sts unasec,temp ;unasec = seksec
736 ;
737 dsk_chkuna:
738 ;check for write to unallocated sector
739 lds temp,unacnt ;any unalloc remain?
740 tst temp
741 breq dsk_alloc ;skip if not
742
743 ; more unallocated records remain
744 dec temp ;unacnt = unacnt-1
745 sts unacnt,temp
746 lds temp,seekdsk ;same disk?
747 lds temp2,unadsk
748 cp temp,temp2 ;seekdsk = unadsk?
749 brne dsk_alloc ;skip if not
750
751 ; disks are the same
752 lds temp,unatrk
753 lds temp2,unatrk+1
754 lds temp3,seektrk
755 lds temp4,seektrk+1
756 cp temp,temp3 ;seektrk = unatrk?
757 cpc temp2,temp4
758 brne dsk_alloc ;skip if not
759
760 ; tracks are the same
761 lds temp,seeksec ;same sector?
762 lds temp2,unasec
763 cp temp,temp2 ;seeksec = unasec?
764 brne dsk_alloc ;skip if not
765
766 ; match, move to next sector for future ref
767 inc temp2 ;unasec = unasec+1
768 sts unasec,temp2
769 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
770 brlo dsk_noovf ;skip if no overflow
771
772 ; overflow to next track
773 sts unasec,_0 ;unasec = 0
774 lds temp,unatrk
775 lds temp2,unatrk+1
776 subi temp, low(-1) ;unatrk = unatrk+1
777 sbci temp2,high(-1)
778 sts unatrk,temp
779 sts unatrk+1,temp2
780 ;
781 dsk_noovf:
782 cbi flags,rsflag ;rsflag = 0
783 rjmp dsk_rwoper ;to perform the write
784 ;
785 dsk_alloc:
786 ;not an unallocated record, requires pre-read
787 sts unacnt,_0 ;unacnt = 0
788 sbi flags,rsflag ;rsflag = 1
789 rjmp dsk_rwoper
790
791 dsk_write_err:
792 ret
793
794 ; ====================================================================
795 ; Function: Does a Disk read/write operation
796 ; ====================================================================
797 ; Parameters
798 ; --------------------------------------------------------------------
799 ; Registers : none
800 ; Variables : [r] seekdsk Number of Disk to Read
801 ; [r] seeksec Sector to read
802 ; [r] seektrk Track to read
803 ; --------------------------------------------------------------------
804 ; Description:
805 ; ====================================================================
806 dsk_rwoper:
807 ;enter here to perform the read/write
808 .if DISK_DEBUG
809 printstring ", flags: "
810 in temp,flags
811 rcall printhex
812 .endif
813 sts erflag,_0 ;no errors (yet)
814
815 ;Convert track/sector to an LBA address (in 128byte blocks)
816
817 lds xl,seeksec ;
818 ldi xh,0 ;
819 ldi yl,0 ;
820 lds temp3,seektrk ;
821 lds temp4,seektrk+1 ;
822 ldi temp,CPMSPT ;
823 mul temp3,temp ;
824 add xl,r0 ;
825 adc xh,r1 ;
826 mul temp4,temp ;
827 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
828 adc yl,r1 ;
829
830 mov temp,xl
831 andi temp,SECMSK ;mask buffer number
832 push temp ;save for later
833
834 ;Convert from CP/M LBA blocks to host LBA blocks
835 ldi temp,SECSHF
836 dsk_sh1:
837 lsr yl
838 ror xh
839 ror xl
840 dec temp
841 brne dsk_sh1
842 ;yl:xh:xl = host block to seek
843 ; active host sector?
844 in _tmp0,flags ;host active flag
845 sbi flags,hostact ;always becomes 1
846 sbrs _tmp0,hostact ;was it already?
847 rjmp dsk_filhst ;fill host if not
848
849 ; host buffer active, same as seek buffer?
850 lds temp,seekdsk
851 lds temp2,hostdsk ;same disk?
852 cp temp,temp2 ;seekdsk = hostdsk?
853 brne dsk_nomatch
854
855 ; same disk, same block?
856 lds temp,hostlba
857 lds temp2,hostlba+1
858 lds temp3,hostlba+2
859 cp xl,temp
860 cpc xh,temp2
861 cpc yl,temp3
862 breq dsk_match
863 ;
864 dsk_nomatch:
865 ;proper disk, but not correct sector
866 sbis flags,hostwrt ;host written?
867 rjmp dsk_filhst
868 push xl
869 push xh
870 push yl
871 rcall dsk_writehost ;clear host buff
872 pop yl
873 pop xh
874 pop xl
875
876 dsk_filhst:
877 ;may have to fill the host buffer
878 lds temp,seekdsk
879 sts hostdsk,temp
880 sts hostlba,xl
881 sts hostlba+1,xh
882 sts hostlba+2,yl
883
884 sbic flags,rsflag ;need to read?
885 rcall dsk_readhost ;yes, if 1
886 cbi flags,hostwrt ;no pending write
887
888 dsk_match:
889
890 ;copy data to or from buffer
891 ldiw z,hostbuf
892 ldi temp,128
893 pop temp2 ;get buffer number (which part of hostbuf)
894 mul temp2,temp
895 add zl,r0 ;offset in hostbuf
896 adc zh,r1
897
898 .if DISK_DEBUG > 2
899 push r0
900 push r1
901 printstring "; host buf adr: "
902 pop temp2
903 pop temp
904 rcall printhexw
905 .endif
906
907 lds xl,dmaadr
908 lds xh,dmaadr+1
909 ldi temp3,128 ;length of move
910 sbic flags,readop ;which way?
911 rjmp dsk_rmove ;skip if read
912
913 ; mark write operation
914 sbi flags,hostwrt ;hostwrt = 1
915 dsk_wmove:
916 mem_read
917 st z+,temp
918 adiw xl,1
919 dec temp3
920 brne dsk_wmove
921 rjmp dsk_rwmfin
922
923 dsk_rmove:
924 ld temp,z+
925 mem_write
926 adiw xl,1
927 dec temp3
928 brne dsk_rmove
929 dsk_rwmfin:
930 ; data has been moved to/from host buffer
931 lds temp,wrtype ;write type
932 cpi temp,WRDIR ;to directory?
933 breq dsk_wdir
934 ret ;no further processing
935 dsk_wdir:
936 ; clear host buffer for directory write
937 lds temp,erflag
938 tst temp ;errors?
939 breq dsk_wdir1
940 ret ;skip if so
941 dsk_wdir1:
942 rcall dsk_writehost ;clear host buff
943 cbi flags,hostwrt ;buffer written
944 ret
945
946 ; ====================================================================
947 ; Function: Does a Disk write operation
948 ; ====================================================================
949 ; Parameters
950 ; --------------------------------------------------------------------
951 ; Registers : none
952 ; Variables : [r] seekdsk Number of Disk to Read
953 ; [r] seeksec Sector to read
954 ; [r] seektrk Track to read
955 ; --------------------------------------------------------------------
956 ; Description:
957 ; ====================================================================
958 dsk_writehost:
959 lds xl,hostdsk
960 rcall dsk_getpartentry
961 ld temp,z
962
963 #if FAT16_SUPPORT
964 ; Is it a FAT16 Diskimage ?
965 cpi temp,dskType_FAT
966 brne PC+2
967 rjmp fat_writehost
968 #endif
969
970 ; Is it a CP/M Partition ?
971 cpi temp,dskType_CPM
972 brne PC+2
973 rjmp cpm_writehost
974 ; Disktype not supported -> Return
975 ret
976
977 ; ====================================================================
978 ; Function: Does a Disk read operation
979 ; ====================================================================
980 ; Parameters
981 ; --------------------------------------------------------------------
982 ; Registers : none
983 ; Variables : [r] seekdsk Number of Disk to Read
984 ; [r] seeksec Sector to read
985 ; [r] seektrk Track to read
986 ; --------------------------------------------------------------------
987 ; Description:
988 ; ====================================================================
989 dsk_readhost:
990 lds xl,hostdsk
991 rcall dsk_getpartentry
992 ld temp,z
993
994 #if FAT16_SUPPORT
995 ; Is it a FAT16 Diskimage ?
996 cpi temp,dskType_FAT
997 brne PC+2
998 rjmp fat_readhost
999 #endif
1000
1001 ; Is it a CP/M Partition ?
1002 cpi temp,dskType_CPM
1003 brne PC+2
1004 rjmp cpm_readhost
1005 ; Disktype not supported -> Return
1006 ret
1007