]> cloudbase.mooo.com Git - avrcpm.git/blob - avr/dsk_fat16.asm
* cpm/BIOS.MAC
[avrcpm.git] / avr / dsk_fat16.asm
1 ; Various functions for the Interaction with the FAT16 Filesystem
2 ;
3 ; Copyright (C) 2010 Frank Zoll
4 ; Copyright (C) 2010 Sprite_tm
5 ; Copyright (C) 2010,2013 Leo C.
6 ;
7 ; This file is part of avrcpm.
8 ;
9 ; avrcpm is free software: you can redistribute it and/or modify it
10 ; under the terms of the GNU General Public License as published by
11 ; the Free Software Foundation, either version 3 of the License, or
12 ; (at your option) any later version.
13 ;
14 ; avrcpm is distributed in the hope that it will be useful,
15 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ; GNU General Public License for more details.
18 ;
19 ; You should have received a copy of the GNU General Public License
20 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
21 ;
22 ; $Id$
23 ;
24
25 ; ============================================================================
26 ; Prelimitary !
27 ; °°°°°°°°°°°°°
28 ; Size of a Sector is fixed to 512 Bytes by Base - MMC Driver implementation
29 ; The Functions below therefore assume a fixed Size of 512 Bytes per Sector.
30 ; ============================================================================
31
32 #if FAT16_SUPPORT
33
34
35 ; ############################################################################
36 ; Defines for FAT16 Structures
37 ; ############################################################################
38
39 /*These are the Offsets to the Variables within the Bootsector of a FAT16
40 Partition.
41 */
42 ;#define FAT16_BSO_SECSIZE 0x0b ; Offset to Sectorsize Word
43 #define FAT16_BSO_CLUSTSZ 0x0d ; Offset to Clustersize Byte
44 #define FAT16_BSO_RESSECT 0x0e ; Offset to Number of Reserved Sectors
45 #define FAT16_BSO_VOLPTR 0x1c ; Offset to First VolumeSector
46 #define FAT16_BSO_SECPERFAT 0x16 ; Offset to Number of Sectors per Fat
47 #define FAT16_BSO_NUMFATCP 0x10 ; Offset to Ammount of FAT Copys
48 #define FAT16_BSO_NUMDIRENT 0x11 ; Offset to Max. Root Dir. entries
49
50 #define FAT16_FIRST_IMAGENAME 'A' /* First letter of filename to search */
51 #define FAT16_LAST_IMAGENAME 'Z' /* Last letter of filename to */
52 #define FAT16_IMAGENAME_PREFIX "CPMDSK_"
53 #define FAT16_IMAGENAME_SUFFIX "IMG"
54
55 ; ############################################################################
56 ; Start of Data Segment
57 ; ############################################################################
58
59 .dseg
60
61 fat_vars:
62 fat_partfound: .byte 1 ; (partition: 0= no found 0xff=found )
63 fat_parttbl: .byte 4 ; first fat16 partition entry
64 ; only startsector is needed
65 fat_clustersize: .byte 1 ; sectors per cluster
66 fat_ptr2fat: .byte 4 ; pointer to the first fat sector
67 fat_ptr2dat: .byte 4 ; pointer to the first data sector
68
69 /*These variables define a cache that holds the last Cluster and Sector
70 thats been searched vor.
71 */
72 fat_last_dsk: .byte 1 ; number of disk with entry in cache
73 fat_log_clust: .byte 2 ; last searched logical cluster
74 fat_clust_offset: .byte 1 ; offset within the cluster
75 fat_clust_ptr: .byte 4 ; sector of last real cluster
76
77 .equ o_fat_partfound = 0
78 .equ o_fat_parttbl = 1
79 .equ o_fat_clustersize = 5
80 .equ o_fat_ptr2fat = 6
81 .equ o_fat_ptr2dat = 10
82 .equ o_fat_last_dsk = 14
83 .equ o_fat_log_clust = 15
84 .equ o_fat_clust_offset= 17
85 .equ o_fat_clust_ptr = 18
86
87 .if SRAM_SIZE > 1024
88
89 fat_last_fatsect: .byte 1
90 .equ o_fat_last_fatsect = 22
91
92 fat_buf: .byte 512
93
94 .endif
95
96 ; ############################################################################
97 ; Start of Code Segment
98 ; ############################################################################
99
100 .cseg
101
102 fat_cfname: .db FAT16_IMAGENAME_PREFIX, 0
103 fat_cfext: .db FAT16_IMAGENAME_SUFFIX, 0
104
105
106 ; ============================================================================
107 ; Function: Initialize internal FAT-Partition Variables
108 ; ============================================================================
109 ; Parameters
110 ; ----------------------------------------------------------------------------
111 ; Registers : none
112 ; Variables : [out] fat_parttabl
113 ; ----------------------------------------------------------------------------
114 ; Description:
115 ; This Routine initializes the internal Variables, that point to the
116 ; first Found FAT16 Partition.
117 ; ============================================================================
118 fat_init_partitiontable:
119
120 ldiw y,fat_vars
121 std y+o_fat_partfound, _0
122 std y+o_fat_parttbl+0, _0
123 std y+o_fat_parttbl+1, _0
124 std y+o_fat_parttbl+2, _0
125 std y+o_fat_parttbl+3, _0
126 ret
127
128
129 ; ============================================================================
130 ; Function: Resets the Cache
131 ; ============================================================================
132 ; Parameters
133 ; ----------------------------------------------------------------------------
134 ; Registers : none
135 ; Variables : [out] fat_log_clust
136 ; [out] fat_last_dsk
137 ; ----------------------------------------------------------------------------
138 ; Description:
139 ; This Routine resets the internal Cache- Variables. After reset, the
140 ; next read or write Command will initialize a scan of the FAT of
141 ; the FAT16-Partition for the given sector.
142 ; ============================================================================
143 fat_reset_cache:
144 ldiw y,fat_vars
145 std y+o_fat_log_clust ,_255
146 std y+o_fat_log_clust+1,_255
147 std y+o_fat_last_dsk ,_255
148 .if SRAM_SIZE > 1024
149 std y+o_fat_last_fatsect,_255
150 .endif
151
152 ret
153
154 ; ============================================================================
155 ; Function: Saves FAT16 Partitiondata for later Scanning
156 ; ============================================================================
157 ; Parameters
158 ; ----------------------------------------------------------------------------
159 ; Registers : [in] z Pointer to the Partitondata
160 ; Variables : [out] fat_partfound Boolean for "Partition found"
161 ; [out] fat_parttbl Pointer to Partitiontable
162 ; ----------------------------------------------------------------------------
163 ; Description:
164 ; This funktion sets the internal Variables to the Start and Size
165 ; of a given FAT16 Paritition. This Information will be used for a
166 ; later scanning of the Partition. See Function "fat_scan_partition"
167 ; for more information.
168 ; ============================================================================
169
170 fat_add_partition:
171
172 .if FAT16_DEBUG > 0
173 printstring "fat16 part found"
174 printnewline
175 .endif
176
177 ldiw y,fat_vars
178
179 ; set fat16 partition found flag
180
181 std y+o_fat_partfound,_255
182
183 ; save data from first fat16 partition
184
185 ldd temp,z+PART_START
186 std y+o_fat_parttbl,temp
187 ldd temp,z+PART_START+1
188 std y+o_fat_parttbl+1,temp
189 ldd temp,z+PART_START+2
190 std y+o_fat_parttbl+2,temp
191 ldd temp,z+PART_START+3
192 std y+o_fat_parttbl+3,temp
193
194 ret
195
196 ; ============================================================================
197 ; Read and Scann a FAT16 Partition for Imagedatefiles
198 ; ============================================================================
199 ; Registers : none
200 ; Variables : none
201 ; ----------------------------------------------------------------------------
202 ; This Routine reads the Bootblock and scanns it for a Diskimage
203 ; ============================================================================
204
205
206 fat_scan_partition:
207
208 .if FAT16_DEBUG > 0
209 printstring "fat16 scanning"
210 printnewline
211 .endif
212
213 ; Check if a FAT16 Partition was realy found
214 lds yl,fat_partfound
215 cpi yl,0
216 breq fat_scan_error
217
218
219 .if FAT16_DEBUG > 0
220 printstring "free entries in ptable ?"
221 printnewline
222 .endif
223
224 ; Check for free entries in partition table
225 lds yl,ndisks
226 cpi yl,MAXDISKS
227 brge fat_scan_error
228
229 .if FAT16_DEBUG > 0
230 printstring "read fat bootblock."
231 printnewline
232 .endif
233
234 ; Scan partition start
235 ldiw z,fat_parttbl
236 ldd xl,z+0
237 ldd xh,z+1
238 ldd yl,z+2
239 ldd yh,z+3
240 ldiw z,hostbuf
241
242 ; Load first sector from Partition
243 rcall mmcReadSect
244 tst temp
245 breq fat_bootblock_check
246
247 ; Read error: Block not found
248 fat_scan_error:
249 clr temp
250 ret
251
252 fat_bootblock_check:
253
254 .if FAT16_DEBUG > 0
255 printstring "fat16 bootblock check"
256 printnewline
257 .endif
258
259 ldiw y,fat_vars
260 ldiw z,hostbuf
261
262 ; get sectors per cluster from bootblock
263 ldd temp,z+FAT16_BSO_CLUSTSZ
264 std y+o_fat_clustersize,temp
265
266 .if FAT16_DEBUG > 0
267 printstring "Sectors per Cluster "
268 lcall printhex
269 printnewline
270 .endif
271
272 ; get max num of entries in root direktory from bootblock
273 ldd temp ,z+FAT16_BSO_NUMDIRENT
274 ldd temp2,z+FAT16_BSO_NUMDIRENT+1
275
276 .if FAT16_DEBUG > 0
277 printstring "Max. entries in rootdir.: "
278 lcall printhexw
279 .endif
280
281 ; Calculate begin of DATA Clusters within the Volume
282 ; Num. Dir.Sektors = (Num. of Dir. entries * 32) / Bytes per Sektor
283
284 ; Sectorsize is fixed at 512 bytes, makes 16 entries per sector
285
286
287 ; Num. Direntries / 16
288 lsr temp2
289 ror temp
290 lsr temp2
291 ror temp
292 lsr temp2
293 ror temp
294 lsr temp2
295 ror temp
296
297 push temp ;save # of rootdir sectors
298
299 .if FAT16_DEBUG > 0
300 printstring " ("
301 movw temp,_tmp0
302 lcall printhex
303 printstring " sectors)"
304 printnewline
305 .endif
306
307 .if FAT16_DEBUG > 1
308 ; Print begin of Volume
309 printstring "Begin of Volume at: "
310 ldd temp, y+o_fat_parttbl+2
311 ldd temp2,y+o_fat_parttbl+3
312 lcall printhexw
313 ldd temp, y+o_fat_parttbl+0
314 ldd temp2,y+o_fat_parttbl+1
315 lcall printhexw
316 printnewline
317 .endif
318
319 ; get num of reseved sectors from bootblock
320 ldd _tmp0,z+FAT16_BSO_RESSECT
321 ldd _tmp1,z+FAT16_BSO_RESSECT+1
322
323 ; Calculate begin of FAT within the Volume
324 ldd xl,y+o_fat_parttbl+0
325 ldd xh,y+o_fat_parttbl+1
326 ldd temp,y+o_fat_parttbl+2
327 ldd temp2,y+o_fat_parttbl+3
328
329 add xl,_tmp0
330 adc xh,_tmp1
331 adc temp,_0
332 adc temp2,_0
333
334 std y+o_fat_ptr2fat ,xl
335 std y+o_fat_ptr2fat+1,xh
336 std y+o_fat_ptr2fat+2,temp
337 std y+o_fat_ptr2fat+3,temp2
338
339 .if FAT16_DEBUG > 1
340 printstring "Begin of FAT at___: "
341 lcall printhexw
342 movw temp ,x
343 lcall printhexw
344 printnewline
345 .endif
346
347 ; get num of sectors per FAT-Table from bootblock
348 ldd temp, z+FAT16_BSO_SECPERFAT
349 ldd temp2,z+FAT16_BSO_SECPERFAT+1
350
351 .if FAT16_DEBUG > 0
352 printstring "Sectors per FAT___: "
353 lcall printhexw
354 printnewline
355 .endif
356
357 ; get num of FAT Tables from bootblock
358 ldd temp3,z+FAT16_BSO_NUMFATCP
359
360 .if FAT16_DEBUG > 0
361 printstring "Ammount of FAT copies: "
362 push temp
363 mov temp,temp3
364 lcall printhex
365 pop temp
366 printnewline
367 .endif
368
369 movw _tmp0,temp
370
371 ; Calculate begin of Root- Directory within the Volume
372
373 ldd xl, y+o_fat_ptr2fat+0
374 ldd xh, y+o_fat_ptr2fat+1
375 ldd temp, y+o_fat_ptr2fat+2
376 ldd temp2,y+o_fat_ptr2fat+3
377
378 fat_calc_dp_loop:
379 cp temp3,_0
380 breq fat_calc_dp_lend
381
382 add xl,_tmp0
383 adc xh,_tmp1
384 adc temp,_0
385 adc temp2,_0
386 dec temp3
387 rjmp fat_calc_dp_loop
388
389 fat_calc_dp_lend:
390
391 .if FAT16_DEBUG > 1
392 printstring "Begin of DIR at___: "
393 lcall printhexw
394 push temp2
395 push temp
396 movw temp,x
397 lcall printhexw
398 pop temp
399 pop temp2
400 printnewline
401 .endif
402
403 pop temp3 ;number of rootdir sectors
404
405 add xl,temp3
406 adc xh,_0
407 adc temp,_0
408 adc temp2,_0
409
410 std y+o_fat_ptr2dat ,xl
411 std y+o_fat_ptr2dat+1,xh
412 std y+o_fat_ptr2dat+2,temp
413 std y+o_fat_ptr2dat+3,temp2
414
415 .if FAT16_DEBUG > 1
416 printstring "Begin of Data at__: "
417 lcall printhexw
418 movw temp ,x
419 lcall printhexw
420 printnewline
421 .endif
422
423 ;-------------------------------------------------------------------------------
424 ; Here starts the scan of the directory for valid image files.
425
426
427 fat_next_sector_loop:
428
429 ; Get a pointer to the last+1 directory sector
430 lds xl,fat_ptr2dat
431 lds xh,fat_ptr2dat+1
432 lds yl,fat_ptr2dat+2
433 lds yh,fat_ptr2dat+3
434
435 ; Add actual offset
436 sub xl,temp3
437 sbc xh,_0
438 sbc yl,_0
439 sbc yh,_0
440
441 ; Load sector from Directory
442 ldiw z,hostbuf
443 lcall mmcReadSect
444 tst temp
445 breq fat_look_for_images
446
447 ; Read error: Block not found
448 clr temp
449 ret
450
451 ; Looks at a read directory block for image entries
452 fat_look_for_images:
453
454 ldiw x,hostbuf
455
456 fat_look_for_loop:
457
458 movw y,x
459 ldiw z,fat_cfname*2
460 ldi temp2,STRLEN(FAT16_IMAGENAME_PREFIX)
461 lcall strncmp_p
462 brne fat_look_continue
463
464 adiw y,1
465 adiw z,1
466 ldi temp2,STRLEN(FAT16_IMAGENAME_SUFFIX)
467 lcall strncmp_p
468 brne fat_look_continue
469
470 movw y,x
471 ldd temp2,y+STRLEN(FAT16_IMAGENAME_PREFIX)
472 ldi temp,FAT16_FIRST_IMAGENAME
473 fat_look_imgname_loop:
474 cp temp,temp2
475 breq fat_look_imgname_match
476 inc temp
477 cpi temp,FAT16_LAST_IMAGENAME+1
478 brlo fat_look_imgname_loop
479 rjmp fat_look_continue
480
481 fat_look_imgname_match:
482 rcall fat_store_new_entry
483 movw x,y
484
485 fat_look_continue:
486
487 adiw x,32
488 ldi temp,high(hostbuf+HOSTSIZE)
489 cpi xl,low(hostbuf+HOSTSIZE)
490 cpc xh,temp
491 brne fat_look_for_loop
492
493 fat_scan_next_sector:
494
495 dec temp3
496 brne fat_next_sector_loop
497
498 ret
499
500
501
502 #if 0
503 dbg_print_parttbl_raw:
504 push zh
505 push zl
506 push temp2
507 push temp
508 ldiw z,hostparttbl
509 dbg_pptblraw_lp:
510 lcall dbg_hexdump_line
511 adiw z,PARTENTRY_SIZE
512 cpi zl,low(hostparttbltop)
513 ldi temp,high(hostparttbltop)
514 cpc zh,temp
515 brne dbg_pptblraw_lp
516 pop temp
517 pop temp2
518 pop zl
519 pop zh
520 ret
521 #endif
522
523 ;-------------------------------------------------------------------------------
524 ; Create new Partition Entry
525 ; ============================================================================
526 ; Function: Create new Partition Entry
527 ; ============================================================================
528 ; Parameters: [in] yh,yl Directory entry
529 ;
530 ; ----------------------------------------------------------------------------
531 ; Registers :
532 ; Variables : [used]
533 ; [changes] temp
534 ; ----------------------------------------------------------------------------
535 ; Description:
536 ;
537 ; ============================================================================
538
539 fat_store_new_entry:
540
541 ; Found a valid image
542 .if FAT16_DEBUG > 1
543 printnewline
544 printstring "Found a valid Image! Y="
545 push temp2
546 push temp
547 movw temp ,y
548 lcall printhexw
549 pop temp
550 pop temp2
551 printnewline
552 .endif
553
554 #if 0
555 ;;;;
556 printstring "Insert entry in Tab: --> "
557 mov temp,temp2
558 lcall uartputc
559 printnewline
560 printstring "Tab before:"
561
562 rcall dbg_print_parttbl_raw
563 printnewline
564 ;;;;
565 #endif
566 ldiw z,hostparttbl
567
568 fat_st_searchpos:
569 ldd temp,z+PTAB_TYPE
570 tst temp
571 breq fat_st_insert_slot
572 sbrs temp,log2(dskType_FAT)
573 rjmp fat_st_search_next
574
575 ldd temp,z+PTAB_START+2
576 cp temp2,temp
577 brlo fat_st_ins_before
578
579 fat_st_search_next:
580 adiw z,PARTENTRY_SIZE
581 cpi zl,low(hostparttbltop)
582 ldi temp,high(hostparttbltop)
583 cpc zh,temp
584 brne fat_st_searchpos
585
586 ; Table is full.
587 #if 0
588 ;;;;
589 push temp2
590 push temp
591 printstring "Table is full. --> ptr: "
592 movw temp,z
593 lcall printhexw
594 printnewline
595 pop temp
596 pop temp2
597 ;;;;
598 #endif
599 ret
600
601 fat_st_ins_before:
602 movw x,z
603 ldiw z,hostparttbltop-PARTENTRY_SIZE
604 fat_st_insert_mkslotloop:
605 cp zl,xl
606 cpc zh,xh
607 breq fat_st_insert_slot
608
609 ld _tmp0,-z
610 std z+PARTENTRY_SIZE,_tmp0
611 rjmp fat_st_insert_mkslotloop
612
613 fat_st_insert_slot:
614
615 ; Set Type of Partition to FAT16- Fileimage
616 ldi temp,dskType_FAT
617 std z+PTAB_TYPE,temp
618
619 ; Offset to Startcluster + 2
620 ldd _tmp0,y+0x1A
621 ldd _tmp1,y+0x1B
622 std z+PTAB_START, _tmp0
623 std z+PTAB_START+1,_tmp1
624
625 std z+PTAB_START+2,temp2
626 std z+PTAB_START+3,_0
627
628 ; Convert Filesize to ammount of sectors
629 ; (calc with 512byte/sector)
630 ldd _tmp0,y+0x1C
631 ldd xl, y+0x1D
632 ldd xh, y+0x1E
633 ldd temp, y+0x1F
634
635 clc
636 cpse _tmp0,_0 ;round up
637 adiw x,1
638 adc temp,_0
639
640 lsr temp
641 ror xh
642 ror xl
643
644 adc xl,_0
645 adc xh,_0
646 adc temp,_0
647
648 ; store ammount of sectors in partitiontable
649
650 tst temp ;file size larger than 65535 sectors?
651 breq fat_add_noprune
652
653 ldi xl,255
654 ldi xh,255
655 fat_add_noprune:
656 std z+PTAB_SIZE, xl
657 std z+PTAB_SIZE+1,xh
658
659 .if FAT16_DEBUG > 1
660 ; Test finding of the first sector
661
662 push yh
663 push yl
664 ldd xl,z+1
665 ldd xh,z+2
666
667 ldiw y,fat_vars
668 rcall fat_gethostsec
669
670 printstring "Begin of image at: "
671 lcall printhexw
672 movw temp ,x
673 lcall printhexw
674 printnewline
675 pop yl
676 pop yh
677 .endif
678
679
680 ; Table counts one more entry if it was'nt allready full
681
682 lds temp,ndisks
683 cpi temp,MAXDISKS
684 breq fat_add_nomore
685 inc temp
686 sts ndisks,temp
687
688 fat_add_nomore:
689
690 #if 0
691 ;;;;
692 printnewline
693 printstring "Table now:"
694 rcall dbg_print_parttbl_raw
695 printnewline
696 ;;;;
697 #endif
698 ret
699
700
701 ; ============================================================================
702 ; Function: Cluster to HostSector
703 ; ============================================================================
704 ; Registers: [in] xl,xh Cluster Number
705 ; [out] yh,yl,xh,xl Sector Number on Disk
706 ; Variables: [in] fat_clustersize Ammount of Sectors per Cluster
707 ; [out] temp =0
708 ; ----------------------------------------------------------------------------
709 ; Description:
710 ; Calculates the logical Sectornumber given the physical ClusterNumber
711 ; and the size of a Cluster un sectors.
712 ;
713 ; ! Only works with Clustersizes 2,4,8,16,32,64,128 !
714 ; ============================================================================
715 fat_gethostsec:
716
717 ; Get Offset into Data area of Disk
718
719 clr _tmp0
720 clr _tmp1
721 sbiw x,2 ; Substract the 2 reserved clusters
722
723 ldd temp,y+o_fat_clustersize
724 lsr temp
725 fat_c2s_loop:
726 tst temp
727 breq fat_c2s_end
728 lsr temp
729
730 lsl xl
731 rol xh
732 rol _tmp0
733 rol _tmp1
734 rjmp fat_c2s_loop
735 fat_c2s_end:
736
737 ; Add begin of data area to offset
738
739 ldd temp,y+o_fat_ptr2dat+0
740 add xl,temp
741 ldd temp,y+o_fat_ptr2dat+1
742 adc xh,temp
743 ldd temp,y+o_fat_ptr2dat+2
744 adc _tmp0,temp
745 ldd temp,y+o_fat_ptr2dat+3
746 adc _tmp1,temp
747 movw temp,_tmp0
748
749 ret
750
751 ; ====================================================================
752 ; Function: Searches a physical Cluster, given the logical Cluster
753 ; ====================================================================
754 ; Registers: [in] xh:xl logical- Cluster
755 ; [out] temp2:temp physical- Cluster
756 ; Variables:
757 ; --------------------------------------------------------------------
758 ; Description:
759 ; ====================================================================
760
761 fat_find_phsy_clust:
762
763 lds zl,hostdsk
764 rcall dsk_getpartentry ; get partition entry
765
766 .if FAT16_DBG_FAT > 0
767 printstring "Search log. cluster "
768 movw temp,x
769 lcall printhexw
770 printnewline
771 .endif
772
773 ; Get First FAT- Cluster Number of Diskimage
774
775 ldd temp, z+1
776 ldd temp2,z+2
777
778 .if FAT16_DBG_FAT > 0
779 printstring "Search phys. cluster "
780 lcall printhexw
781 printnewline
782 .endif
783
784 fat_next_phsy_clust:
785 cp xl,_0
786 cpc xh,_0
787 breq fat_found_phsy_clust
788
789 ; Get Next Cluster from Fat
790
791 ; Trick: 512 Bytes Per Sector equals to 256 FAT- entries per Sector
792 ; so given: temp is the Offset within the FAT Sector
793 ; temp2 is the number off the FAT sector to Read
794
795 push xl
796 push xh
797
798 ; Create FAT Offset Value
799
800 clr zh
801 mov zl,temp
802 lsl zl
803 rol zh
804
805 .if SRAM_SIZE > 1024
806
807 ; Check, if required fat sector allready in buffer
808
809 ldd temp,y+o_fat_last_fatsect
810 std y+o_fat_last_fatsect,temp2
811 cp temp,temp2
812 breq fat_phys_1
813
814 ; Not in buffer, get fat sector
815
816 ldd xl, y+o_fat_ptr2fat ;get FAT start
817 ldd xh, y+o_fat_ptr2fat+1
818 ldd _tmp0,y+o_fat_ptr2fat+2
819 ldd _tmp1,y+o_fat_ptr2fat+3
820 add xl,temp2 ;add cluster offset within sector
821 adc xh,_0
822 adc _tmp0,_0
823 adc _tmp1,_0
824 movw y,_tmp0
825 .if 0
826 printnewline
827 printstring "Read FAT sec: "
828 mov temp,temp2
829 lcall printhex
830 printstring ", "
831 movw temp,z
832 lcall printhexw
833 printstring " "
834 .endif
835 push zl
836 push zh
837 ldiw z,fat_buf
838
839 ; in zh,zl Pointer to Word within the Sector to read
840 ; in yh..xl Start sector number (LBA)
841 ; out zh,zl word thats been read
842 lcall mmcReadSect
843 pop zh
844 pop zl
845
846 fat_phys_1:
847 ldiw y,fat_buf
848 add zl,yl
849 adc zh,yh
850 ldd temp, z+0
851 ldd temp2,z+1
852 ldiw y,fat_vars
853 .else
854
855 ldd xl,y+o_fat_ptr2fat ;get FAT start
856 ldd xh,y+o_fat_ptr2fat+1
857 ldd _tmp0,y+o_fat_ptr2fat+2
858 ldd _tmp1,y+o_fat_ptr2fat+3
859 movw y,_tmp0
860 add xl,temp2 ;add cluster offset within sector
861 adc xh,_0
862 adc yl,_0
863 adc yh,_0
864 lcall mmcReadWord
865 movw temp,z
866 ldiw y,fat_vars
867 .endif
868 pop xh
869 pop xl
870
871
872 ; Check next logical Cluster
873
874 sbiw x,1
875 rjmp fat_next_phsy_clust
876
877 ; Found the physical cluster
878 fat_found_phsy_clust:
879
880 .if FAT16_DBG_FAT > 0
881 printstring "Found phys. Cluster at:"
882 lcall printhexw
883 printnewline
884 .endif
885
886 ret
887
888 ; ============================================================================
889 ; Function: This Routine searches for the Sector within an Imagefile
890 ; ============================================================================
891 ; Registers: [out] xl,xh,yl,yh Pointer to the sector on the SD-Card
892 ; [out] temp Error variable (0= No Error)
893 ; Variables: [in] hostdsk host disk #, (partition #)
894 ; [in] hostlba host block #, relative to part.start
895 ; [in] fat_last_dsk number of disk with entry in cache
896 ; [in] fat_log_clust last searched logical cluster
897 ; [in] fat_clust_offset offset within the cluster
898 ; [in] fat_clust_ptr sector of last real cluster
899 ; ----------------------------------------------------------------------------
900 ; Description:
901 ; This routine uses the variables hostdsk and hostlba to find an sector
902 ; in the imagefile.
903 ; The CP/M sector given within "hostlba" are splited to a logical cluster-
904 ; number and the subsector within this logical cluster.
905 ; logical cluster number = hostlba / fat_clustersize
906 ; The logical cluster number will be compared to the logical cluster number
907 ; within the cache. When this clusters are the same and the diskid's are
908 ; also the same, then the cached physical sector will be used.
909 ; When the clusters or the disks don't match, a seek for the physical
910 ; cluster is performed. This seek is done thru an access over the fat of
911 ; the fat16 partition. the routine starts at the first cluster of the
912 ; imagefile and goes along the linked list of clusternumber till it reaches
913 ; the searched cluster. The found clusternumber will be used to calculate
914 ; the sektor where this cluster lies on the sd card. Both the found physical
915 ; cluster and the logical cluster together with the physical sectornumber
916 ; are stored in the cache.
917 ; The last step done is to add the subsectoroffset to the found physical
918 ; sector. this gives the pointer to the sector to be read and or written.
919 ; ============================================================================
920
921 fat_lba_to_phys:
922
923 ; ################# Get logical Number of Cluster within the imagefile
924 ; printstring "calc log sector"
925 ; Logical Sectornumber in x
926
927 ldiw y,fat_vars
928
929 movw temp,x
930 mov _tmp0,_0
931 mov _tmp1,_0
932
933 ; Divide logical sectornumber by size of cluster in sectors
934
935 ldd zl,y+o_fat_clustersize
936 lsr zl
937 fat_search_clst_lp:
938 tst zl
939 breq fat_found_clst
940
941 lsr _tmp1
942 ror _tmp0
943 ror xh
944 ror xl
945
946 lsr zl
947
948 rjmp fat_search_clst_lp
949
950 ; at this point xh and xl are carying the logical cluster number
951 ; printstring "find subsector"
952 ; ################# Get subsector within the logical cluster for later use
953
954 fat_found_clst:
955 mov _tmp0,xl
956 ldd zl,y+o_fat_clustersize
957 lsr zl
958 fat_search_clst_lp2:
959 tst zl
960 breq fat_found_subsec
961 lsl _tmp0
962
963 lsr zl
964 rjmp fat_search_clst_lp2
965
966 fat_found_subsec:
967 mov zl,temp
968 sub zl,_tmp0
969 std y+o_fat_clust_offset,zl
970
971 ; Check against last HOSTDISK searched
972 lds _tmp0,hostdsk
973 ldd _tmp1,y+o_fat_last_dsk
974 std y+o_fat_last_dsk,_tmp0
975 cp _tmp0,_tmp1
976 brne fat_wrong_cache_clst
977
978 ; Check against last Cluster searched
979 ldd _tmp0,y+o_fat_log_clust
980 ldd _tmp1,y+o_fat_log_clust+1
981
982 cp _tmp0,xl
983 cpc _tmp1,xh
984 brne fat_wrong_cache_clst
985
986 ; Last Cluster = searched Cluster -> get Sectornumber from cache
987 ldd xl, y+o_fat_clust_ptr
988 ldd xh, y+o_fat_clust_ptr+1
989 ldd temp, y+o_fat_clust_ptr+2
990 ldd temp2,y+o_fat_clust_ptr+3
991
992 rjmp fat_add_offset
993
994 ; Cluster is not in cache, so we must search for it
995 fat_wrong_cache_clst:
996 std y+o_fat_log_clust,xl
997 std y+o_fat_log_clust+1,xh
998
999 ; Map Logical Cluster-Number to "Physical" Cluster Number using the FAT
1000
1001 rcall fat_find_phsy_clust
1002
1003 ; Get StartSector of "physical" Cluster
1004
1005 movw x,temp
1006 rcall fat_gethostsec
1007
1008 ; Found the physical sector
1009
1010 .if FAT16_DBG_FAT > 0
1011 printstring "Found phys. Sector at:"
1012 push temp2
1013 push temp
1014 lcall printhexw
1015 movw temp,x
1016 lcall printhexw
1017 printnewline
1018 pop temp
1019 pop temp2
1020 .endif
1021
1022 ; Save the found Sector for later use into cache
1023
1024 std y+o_fat_clust_ptr ,xl
1025 std y+o_fat_clust_ptr+1,xh
1026 std y+o_fat_clust_ptr+2,temp
1027 std y+o_fat_clust_ptr+3,temp2
1028
1029 ; Add- Subsector to Startsector
1030 fat_add_offset:
1031 ldd zl,y+o_fat_clust_offset
1032 add xl,zl
1033 adc xh,_0
1034 adc temp,_0
1035 adc temp2,_0
1036 movw y,temp
1037
1038 ; Found the physical sector
1039 .if FAT16_DBG_FAT > 0
1040 printstring "Sector with Offset at:"
1041 movw temp,y
1042 lcall printhexw
1043 movw temp,x
1044 lcall printhexw
1045 printnewline
1046 .endif
1047
1048 ret
1049
1050 #endif /* FAT16_SUPPORT */
1051
1052 ; vim:set ts=8 noet nowrap
1053