1 ; Various functions for the Interaction with the FAT16 Filesystem
3 ; Copyright (C) 2010 Frank Zoll
5 ; This file is part of avrcpm.
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.
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.
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/>.
23 ; ===========================================================================
26 ; Size of a Sector is fixed to 512 Bytes by Base - MMC Driver implementation
27 ; The Functions below therefore assume a fixed Size of 512 Bytes per Sector.
28 ; ===========================================================================
33 ;-------------------------------- Defines for FAT16 Structures
34 #define PARTID_FAT16 0x0E
36 ;#define FAT16_BSO_SECSIZE 0x0b ; BootSectorOffset to Sectorsize Word
37 #define FAT16_BSO_CLUSTSZ 0x0d ; BootSectorOffset to Clustersize Byte
38 #define FAT16_BSO_RESSECT 0x0e ; BootSectorOffset to Number of Reserved Sectors
39 #define FAT16_BSO_VOLPTR 0x1c ; BootSectorOffset to First VolumeSector
40 #define FAT16_BSO_SECPERFAT 0x16 ; BootSectorOffset to Number of Sectors per Fat
41 #define FAT16_BSO_NUMFATCP 0x10 ; BootSectorOffset to Ammount of FAT Copys
42 #define FAT16_BSO_NUMDIRENT 0x11 ; BootSectorOffset to Max. Root Dir. Entrys
43 #define FAT16_FIRST_IMAGENAME 'A'
44 #define FAT16_LAST_IMAGENAME 'Z'
46 ;-------------------------------- Start of Data Segment
50 fat_partfound: .byte 1 ; (0= no fat partition found 1=found partition)
51 fat_parttbl: .byte 8 ; first fat16 partition entry (start sector, sector count)
52 ;fat_sectorsize: .byte 2 ; size of sector in bytes
53 fat_clustersize: .byte 1 ; sectors per cluster
54 fat_ressectors: .byte 2 ; number of reserved sectors
55 fat_secperfat: .byte 2 ; number of sectors per fat
56 fat_numfatcp: .byte 1 ; Number of FAT Copies
57 fat_numdirentrys:.byte 2 ; Max. ammount of Directory Entrys within Rootdirektory
58 fat_ptr2fat: .byte 4 ; pointer to the first fat sector
59 fat_ptr2dir: .byte 4 ; pointer to the first root directory sector
60 fat_ptr2dat: .byte 4 ; pointer to the first data sector
62 fat_last_dsk: .byte 1 ; number of disk with entry in cache
63 fat_log_clust: .byte 2 ; last searched logical cluster
64 fat_clust_offset: .byte 1 ; offset within the cluster
65 fat_clust_ptr: .byte 4; ; sector of last real cluster
66 ; ------------------------------- Start of Code Segment
69 ; ====================================================================
70 ; Function: Does a Disk read/write operation
71 ; ====================================================================
73 ; --------------------------------------------------------------------
75 ; Variables : [r] seekdsk Number of Disk to Read
76 ; [r] seeksec Sector to read
77 ; [r] seektrk Track to read
78 ; --------------------------------------------------------------------
80 ; ====================================================================
81 fat_init_partitiontable:
96 ; ====================================================================
97 ; Function: Resets the Cache
98 ; ====================================================================
100 ; --------------------------------------------------------------------
102 ; Variables : [r] seekdsk Number of Disk to Read
103 ; [r] seeksec Sector to read
104 ; [r] seektrk Track to read
105 ; --------------------------------------------------------------------
107 ; ====================================================================
111 sts fat_log_clust ,yl
112 sts fat_log_clust+1,yl
117 ; ====================================================================
118 ; Function: Add's a FAT16 Partition for later Scanning
119 ; ====================================================================
121 ; --------------------------------------------------------------------
124 ; --------------------------------------------------------------------
126 ; This funktion sets the internal Variables to set Start and Size
127 ; of a given FAT16 Paritition. This Information will be used for a
128 ; later scanning of the Partition. See Function "fat_scan_partition"
129 ; for more information.
130 ; ====================================================================
134 printstring "fat16 part found",0
139 ; save variables on stack
143 ; set fat16 partition found flag
147 ; save data from first fat16 partition
150 ldd temp,z+PART_START
152 ldd temp,z+PART_START+1
154 ldd temp,z+PART_START+2
156 ldd temp,z+PART_START+3
161 ldd temp,z+PART_SIZE+1
163 ldd temp,z+PART_SIZE+2
165 ldd temp,z+PART_SIZE+3
169 ; reload variables from stack
175 ; ---------------------------------------------------------------------------
176 ; Read and Scann a FAT16 Partition for Imagedatefiles
177 ; ---------------------------------------------------------------------------
178 ; This Routine reads the Bootblock and scanns it for a Diskimage
179 ; Input Registers : none
180 ; Output Registers : none
181 ; Changes Variables: none
182 ; ---------------------------------------------------------------------------
188 printstring "fat16 scanning",0
192 ; Check if a FAT16 Partition was realy found
199 printstring "free entrys in ptable ?",0
203 ; Check for free Entrys in Partition table
209 printstring "read fat bootblock.",0
213 ; Scan partition start
220 ; Load first sector from Partition
223 breq fat_bootblock_check
225 ; Read error: Block not found
233 printstring "fat16 bootblock check",0
237 ; -> Size of Sectors fixed at 512 Bytes
238 ; Get ammount of Bytes per Sector
239 ; ldiw z,hostbuf+FAT16_BSO_SECSIZE
240 ; ldiw y,fat_sectorsize
247 ; printstring "Bytes per Sector ",0
252 ; Anzahl der Sectoren pro Cluster lesen
253 ldiw z,hostbuf+FAT16_BSO_CLUSTSZ
255 sts fat_clustersize,temp
258 printstring "Sectors per Cluster ",0
263 ; Anzahl der reservierten Sectoren
264 ldiw z,hostbuf+FAT16_BSO_RESSECT
266 sts fat_ressectors,temp ; low byte
268 sts fat_ressectors+1,temp2 ; high byte
271 printstring "Reserved Sectors__: ",0
276 ; Anzahl der Sectoren pro FAT
277 ldiw z,hostbuf+FAT16_BSO_SECPERFAT
279 sts fat_secperfat,temp ; low byte
281 sts fat_secperfat+1,temp2 ; high byte
284 printstring "Sectors per FAT__: ",0
289 ; Anzahl der FAT kopien
290 ldiw z,hostbuf+FAT16_BSO_NUMFATCP
292 sts fat_numfatcp,temp ; low byte
295 printstring "Ammount of FAT copies: ",0
300 ; Max. Anzahl der Dir. Enträge im Root Verz.
301 ldiw z,hostbuf+FAT16_BSO_NUMDIRENT
303 sts fat_numdirentrys,temp ; low byte
305 sts fat_numdirentrys+1,temp2 ; high byte
308 printstring "Max. entrys in Rootdir.: ",0
313 ; Print begin of Volume
322 printstring "Begin of Volume at: ",0
332 ; Calculate begin of FAT within the Volume
333 lds temp ,fat_ressectors
334 lds temp2,fat_ressectors+1
353 printstring "Begin of FAT at___: ",0
363 ; Calculate begin of Root- Directory within the Volume
370 lds temp ,fat_secperfat
371 lds temp2,fat_secperfat+1
372 lds temp3,fat_numfatcp
376 breq fat_calc_dp_lend
395 printstring "Begin of DIR at___: ",0
405 ; Calculate begin of DATA Clusters within the Volume
406 ; Num. Dir.Sektors = (Num. of Dir. Entrys * 32) / Bytes per Sektor
408 ; Sectorsize is fixed at 512 Bytes, makes 16 Entrys per Sektor
410 lds zl,fat_numdirentrys ; low byte
411 lds zh,fat_numdirentrys+1 ; high byte
413 ; Num. Direntrys / 16
439 printstring "Begin of Data at__: ",0
449 ; Here Starts the Scann of the Directory for valid image Files.
451 ; Init Image-Namecounter
452 ldi temp,FAT16_FIRST_IMAGENAME
453 sts fat_last_dsk,temp
455 fat_scan_for_next_image:
457 ; Init Offset into Directory-Sectors
459 sts fat_clust_offset,temp
461 ; Init counter for number of entry left to scan
462 lds temp,fat_numdirentrys
463 sts fat_log_clust ,temp
465 lds temp,fat_numdirentrys+1
466 sts fat_log_clust+1,temp
468 fat_next_sector_loop:
469 ; Get a Pointer to the first Directory sector
476 lds temp,fat_clust_offset
482 ; Load sector from Directory
485 breq fat_look_for_images
487 ; Read error: Block not found
491 ; Looks at a read directory block for image entrys
526 lds temp3,fat_last_dsk ; Get actual Diskname (A to Z)
542 sts fat_clust_ptr ,zl
543 sts fat_clust_ptr+1,zh
544 sts fat_clust_ptr+2,temp2
545 jmp fat_store_new_entry
551 printstring "At:Scann for more ",0
555 lds zl ,fat_clust_ptr
556 lds zh ,fat_clust_ptr+1
557 lds temp2,fat_clust_ptr+2
567 cpi temp2,16 ; max entrys/sector
568 breq fat_scan_next_sector
569 jmp fat_look_for_loop
571 fat_scan_next_sector:
574 printstring "At:Scan next Sector",0
578 lds temp3, fat_log_clust
579 lds temp4, fat_log_clust+1
584 sts fat_log_clust,temp3
585 sts fat_log_clust+1,temp4
591 lds temp,fat_clust_offset
593 sts fat_clust_offset,temp
595 rjmp fat_next_sector_loop
600 printstring "At:Scan at end",0
604 lds temp,fat_last_dsk
606 sts fat_last_dsk,temp
608 ldi temp2,FAT16_LAST_IMAGENAME
610 brge fat_scaned_last_disk
612 rjmp fat_scan_for_next_image
614 fat_scaned_last_disk:
619 ; Create new Partition Entry
622 ; Found a valid image
624 printstring "Found a valid Image ! Z=",0
638 adiw y,PARTENTRY_SIZE
640 jmp fat_look_store_loop
643 ; Set Type of Partition to FAT16- Fileimage
648 printstring "ClusterID",0
650 ; Offset to Startcluster + 2
678 ; Convert Filesize to ammount of sectors
679 ; (calc with 512byte/sector)
690 ; store ammount of sectors in partitiontable
697 ; Test finding of the first sector
704 printstring "Begin of Image at: ",0
714 ; Check for another free entry in partition table
722 jmp fat_scan_for_more
729 ; ====================================================================
730 ; Function: Cluster to HostSector
731 ; ====================================================================
732 ; Parameters: [in] xh,xl Cluster Number
733 ; [out] yh,yl,xh,xl Sector Number on Disk
734 ; --------------------------------------------------------------------
736 ; Variables : [used] fat_clustersize Ammount of Sectors per Cluster
738 ; --------------------------------------------------------------------
740 ; ! Only works with Clustersizes 2,4,8,16,32,64,128 !
741 ; ====================================================================
744 ; Get Offset into Data area of Disk
748 ; add begin of data area to offset
749 lds temp,fat_ptr2dat+0
751 lds temp,fat_ptr2dat+1
753 lds temp,fat_ptr2dat+2
755 lds temp,fat_ptr2dat+3
759 ; ====================================================================
760 ; Function: Cluster to Sector
761 ; ====================================================================
762 ; Parameters: [in] xl,xh Cluster Number
763 ; [out] xl,xh,yl,yh Sector Number
764 ; --------------------------------------------------------------------
766 ; Variables : [used] fat_clustersize Ammount of Sectors per Cluster
768 ; --------------------------------------------------------------------
770 ; ! Only works with Clustersizes 2,4,8,16,32,64,128 !
771 ; ====================================================================
777 sub xl,temp ; Substract the 2 reserved clusters
780 lds temp,fat_clustersize
797 ; ====================================================================
798 ; Function: Searches a physical Cluster, given the logical Cluster
799 ; ====================================================================
801 ; --------------------------------------------------------------------
802 ; Registers : [r] xh,xl logical- Cluster
803 ; [w] yh,yl physical- Cluster
804 ; --------------------------------------------------------------------
806 ; ====================================================================
811 rcall dsk_getpartentry ; get partition entry
814 ; Get First FAT- Cluster Number of Diskimage
819 .if FAT16_DBG_FAT > 0
820 printstring "Search log. Cluster ",0
826 printstring "Search phys. Cluster ",0
836 breq fat_found_phsy_clust
837 ; Get Next Cluster from Fat
839 ; Trick: 512 Bytes Per Sector equals to 256 FAT- Entrys per Sector
840 ; so given: yl is the Offset within the FAT Sector
841 ; yh is the number off se FAT sector to Read
843 ; in zh,zl: Pointer to Word within the Sector to read
844 ; in yh..xl: Start sector number (LBA)
845 ; out zh,zl : word thats been read
849 ; Create FAT Offset Value
860 ; Add Cluster offset within sector
873 ; Check next logical Cluster
877 rjmp fat_next_phsy_clust
879 ; Found the physical cluster
880 fat_found_phsy_clust:
881 .if FAT16_DBG_FAT > 0
882 printstring "Found phys. Cluster at:",0
891 ; ====================================================================
892 ; Function: Does a Disk write operation
893 ; ====================================================================
895 ; --------------------------------------------------------------------
897 ; Variables : [r] seekdsk Number of Disk to Read
898 ; [r] seeksec Sector to read
899 ; [r] seektrk Track to read
900 ; hostdsk = host disk #, (partition #)
901 ; hostlba = host block #, relative to partition start
902 ; Read/Write "hostsize" bytes to/from hostbuf
903 ; --------------------------------------------------------------------
905 ; ====================================================================
911 rcall dsk_getpartentry ; get partition entry
919 ldd xl,z+5 ; get size of disk in sectors
923 cp temp,xl ; check given sector against disksize
932 ; ################# Get logical Number of Cluster within the imagefile
933 ; printstring "calc log sector"
934 ; Get logical Sectornumber from temp
939 ; Divide logical Sectornumber by size of Cluster in sectors
940 lds zl, fat_clustersize
953 rjmp fat_search_clst_lp
955 ; at this point xh and xl are carying the logical cluster number
956 ; printstring "find subsector"
957 ; ################# Get Subsector within the logical Cluster for later use
959 lds zl, fat_clustersize
963 breq fat_found_subsec
967 rjmp fat_search_clst_lp2
972 sts fat_clust_offset,zl
974 ; Check against last HOSTDISK searched
978 brne fat_wrong_cache_clst
980 ; Check against last Cluster searched
982 lds yh,fat_log_clust+1
985 brne fat_wrong_cache_clst
987 brne fat_wrong_cache_clst
989 ; Last Cluster = searched Cluster -> get Sectornumber from cache
991 lds xh,fat_clust_ptr+1
992 lds yl,fat_clust_ptr+2
993 lds yh,fat_clust_ptr+3
997 ; ################# Cluster is not in cache, so we must search for it
998 fat_wrong_cache_clst:
1001 sts fat_log_clust,xl
1002 sts fat_log_clust+1,xh
1004 ; ################# Map Logical Cluster-Number to "Physical" Cluster Number using the FAT
1005 rcall fat_find_phsy_clust
1007 ; ################# Get StartSector of "physical" Cluster
1010 rcall fat_gethostsec
1011 ; Found the physical sector
1012 .if FAT16_DBG_FAT > 0
1013 printstring "Found phys. Sector at:",0
1023 ; Save the found Sector for later use into cache
1024 sts fat_clust_ptr ,xl
1025 sts fat_clust_ptr+1,xh
1026 sts fat_clust_ptr+2,yl
1027 sts fat_clust_ptr+3,yh
1029 ; Add- Subsector to Startsector
1031 lds zl,fat_clust_offset
1037 ; Found the physical sector
1038 .if FAT16_DBG_FAT > 0
1039 printstring "Sector with Offset at:",0
1053 ; ====================================================================
1054 ; Function: Does a Disk write operation
1055 ; ====================================================================
1057 ; --------------------------------------------------------------------
1059 ; Variables : [r] seekdsk Number of Disk to Read
1060 ; [r] seeksec Sector to read
1061 ; [r] seektrk Track to read
1062 ; --------------------------------------------------------------------
1064 ; ====================================================================
1067 .if FAT16_RWDEBUG > 1
1069 printstring "host write "
1074 ;call mmcWriteSect ; disabled till read is functioning
1078 rcall mgr_init_partitions
1084 ;call mmcWriteSect ; disabled till read is functioning
1096 ; ====================================================================
1097 ; Function: Does a Disk read operation
1098 ; ====================================================================
1100 ; --------------------------------------------------------------------
1102 ; Variables : [r] seekdsk Number of Disk to Read
1103 ; [r] seeksec Sector to read
1104 ; [r] seektrk Track to read
1105 ; --------------------------------------------------------------------
1107 ; ====================================================================
1110 .if FAT16_RWDEBUG > 1
1112 printstring "host read "
1119 .if FAT16_RWDEBUG > 0
1120 printstring "Read Image Sector:"
1139 rcall mgr_init_partitions