diff options
-rw-r--r-- | firmware/drivers/fat.c | 286 | ||||
-rw-r--r-- | firmware/drivers/fat.h | 2 |
2 files changed, 115 insertions, 173 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 37b0648c2e..ef6ee8b2ef 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -100,7 +100,7 @@ | |||
100 | #define FATDIR_FILESIZE 28 | 100 | #define FATDIR_FILESIZE 28 |
101 | 101 | ||
102 | #define CLUSTERS_PER_FAT_SECTOR (SECTOR_SIZE / 4) | 102 | #define CLUSTERS_PER_FAT_SECTOR (SECTOR_SIZE / 4) |
103 | #define DIR_ENTRIES_PER_SECTOR (SECTOR_SIZE / 32) | 103 | #define DIR_ENTRIES_PER_SECTOR (SECTOR_SIZE / DIR_ENTRY_SIZE) |
104 | #define DIR_ENTRY_SIZE 32 | 104 | #define DIR_ENTRY_SIZE 32 |
105 | #define FAT_BAD_MARK 0x0ffffff7 | 105 | #define FAT_BAD_MARK 0x0ffffff7 |
106 | #define FAT_EOF_MARK 0x0ffffff8 | 106 | #define FAT_EOF_MARK 0x0ffffff8 |
@@ -596,7 +596,7 @@ static int flush_fat(void) | |||
596 | if (err) | 596 | if (err) |
597 | { | 597 | { |
598 | DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", err); | 598 | DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", err); |
599 | return -1; | 599 | return -3; |
600 | } | 600 | } |
601 | intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]); | 601 | intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]); |
602 | *intptr = SWAB32(fat_bpb.fsinfo.freecount); | 602 | *intptr = SWAB32(fat_bpb.fsinfo.freecount); |
@@ -608,7 +608,7 @@ static int flush_fat(void) | |||
608 | if (err) | 608 | if (err) |
609 | { | 609 | { |
610 | DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", err); | 610 | DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", err); |
611 | return -1; | 611 | return -4; |
612 | } | 612 | } |
613 | 613 | ||
614 | return 0; | 614 | return 0; |
@@ -645,107 +645,68 @@ static int add_dir_entry(struct fat_dir* dir, | |||
645 | struct fat_file* file) | 645 | struct fat_file* file) |
646 | { | 646 | { |
647 | unsigned char buf[SECTOR_SIZE]; | 647 | unsigned char buf[SECTOR_SIZE]; |
648 | unsigned char *eptr; | ||
649 | int i; | ||
650 | int err; | 648 | int err; |
651 | int sec; | 649 | int sector=0; |
652 | int sec_cnt = 0; | 650 | bool update_last = false; |
653 | bool need_to_update_last_empty_marker = false; | ||
654 | bool done = false; | 651 | bool done = false; |
655 | unsigned char firstbyte; | 652 | bool eof = false; |
656 | int currdir = dir->startcluster; | ||
657 | bool is_rootdir = (currdir == 0); | ||
658 | 653 | ||
659 | LDEBUGF( "add_dir_entry(%x,%s,%x)\n", | 654 | LDEBUGF( "add_dir_entry(%x,%s,%x)\n", |
660 | dir->startcluster, de->name, file->firstcluster); | 655 | dir->startcluster, de->name, file->firstcluster); |
661 | 656 | ||
662 | if (is_rootdir) | 657 | err=fat_seek(&dir->file, 0); |
663 | sec = fat_bpb.rootdirsector; | 658 | if (err<0) |
664 | else | 659 | return -1; |
665 | sec = first_sector_of_cluster(currdir); | ||
666 | 660 | ||
667 | while(!done) | 661 | while(!done) |
668 | { | 662 | { |
669 | bool new = false; | 663 | err = 0; |
670 | if (sec_cnt >= fat_bpb.bpb_secperclus) | 664 | if (!eof) { |
671 | { | 665 | err = fat_readwrite(&dir->file, 1, buf, false); |
672 | int oldcluster; | 666 | sector++; |
667 | } | ||
668 | if (err==0) { | ||
669 | /* eof: add new sector */ | ||
670 | eof = true; | ||
673 | 671 | ||
674 | /* we're not adding a whole new sector | 672 | /* don't add a new sector only for the last-entry marker */ |
675 | just for the end-of-dir marker */ | 673 | if (update_last) |
676 | if ( need_to_update_last_empty_marker ) | ||
677 | break; | 674 | break; |
678 | 675 | ||
679 | if (!currdir) | 676 | memset(buf, 0, sizeof buf); |
680 | currdir = sec2cluster(fat_bpb.rootdirsector); | 677 | LDEBUGF("Adding new sector to dir\n"); |
681 | oldcluster = currdir; | 678 | err=fat_seek(&dir->file, sector-1); |
682 | 679 | if (err<0) | |
683 | /* We have reached the end of this cluster */ | ||
684 | LDEBUGF("Moving to the next cluster...\n"); | ||
685 | currdir = get_next_cluster(currdir); | ||
686 | if (!currdir) | ||
687 | { | ||
688 | /* end of dir, add new cluster */ | ||
689 | LDEBUGF("Adding cluster to dir\n"); | ||
690 | currdir = find_free_cluster(oldcluster+1); | ||
691 | if (!currdir) { | ||
692 | DEBUGF("add_dir_entry(): Disk full!\n"); | ||
693 | return -1; | ||
694 | } | ||
695 | update_fat_entry(oldcluster, currdir); | ||
696 | update_fat_entry(currdir, FAT_EOF_MARK); | ||
697 | new = true; | ||
698 | memset(buf, 0, sizeof buf); | ||
699 | |||
700 | /* clear remaining sectors in this cluster */ | ||
701 | if (fat_bpb.bpb_secperclus > 1) { | ||
702 | int i; | ||
703 | sec = cluster2sec(currdir); | ||
704 | for (i=1; i<fat_bpb.bpb_secperclus; i++ ) { | ||
705 | err = ata_write_sectors(sec + fat_bpb.startsector + i, | ||
706 | 1, buf); | ||
707 | if (err) { | ||
708 | DEBUGF( "add_dir_entry() - " | ||
709 | " Couldn't write dir" | ||
710 | " sector (error code %d)\n", err); | ||
711 | return -3; | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | } | ||
716 | LDEBUGF("new cluster is %x\n", currdir); | ||
717 | sec = cluster2sec(currdir); | ||
718 | sec_cnt = 0; | ||
719 | } | ||
720 | |||
721 | if (!new) { | ||
722 | /* Read the next sector in the current dir */ | ||
723 | err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); | ||
724 | if (err) | ||
725 | { | ||
726 | DEBUGF( "add_dir_entry() - Couldn't read dir sector" | ||
727 | " (error code %d)\n", err); | ||
728 | return -2; | 680 | return -2; |
729 | } | 681 | err = fat_readwrite(&dir->file, 1, buf, true); |
682 | if (err<1) | ||
683 | return -3; | ||
684 | } | ||
685 | if (err<0) { | ||
686 | DEBUGF( "add_dir_entry() - Couldn't read dir" | ||
687 | " (error code %d)\n", err); | ||
688 | return -4; | ||
730 | } | 689 | } |
731 | 690 | ||
732 | if (need_to_update_last_empty_marker) | 691 | if (update_last) |
733 | { | 692 | { |
734 | /* All we need to do is to set the first entry to 0 */ | 693 | /* All we need to do is to set the first entry to 0 */ |
735 | LDEBUGF("Clearing the first entry in sector %x\n", sec); | 694 | LDEBUGF("Clearing the first entry in sector %d\n", sector); |
736 | buf[0] = 0; | 695 | buf[0] = 0; |
737 | done = true; | 696 | done = true; |
738 | } | 697 | } |
739 | else | 698 | else |
740 | { | 699 | { |
700 | int i; | ||
741 | /* Look for a free slot */ | 701 | /* Look for a free slot */ |
742 | for (i = 0; i < SECTOR_SIZE; i += DIR_ENTRY_SIZE) | 702 | for (i = 0; i < SECTOR_SIZE; i += DIR_ENTRY_SIZE) |
743 | { | 703 | { |
744 | firstbyte = buf[i]; | 704 | unsigned char firstbyte = buf[i]; |
745 | if (firstbyte == 0xe5 || firstbyte == 0) | 705 | if (firstbyte == 0xe5 || firstbyte == 0) |
746 | { | 706 | { |
747 | LDEBUGF("Found free entry %d in sector %x\n", | 707 | unsigned char* eptr; |
748 | i/DIR_ENTRY_SIZE, sec); | 708 | LDEBUGF("Found free entry %d in sector %d\n", |
709 | i/DIR_ENTRY_SIZE, sector); | ||
749 | eptr = &buf[i]; | 710 | eptr = &buf[i]; |
750 | memset(eptr, 0, DIR_ENTRY_SIZE); | 711 | memset(eptr, 0, DIR_ENTRY_SIZE); |
751 | strncpy(&eptr[FATDIR_NAME], de->name, 11); | 712 | strncpy(&eptr[FATDIR_NAME], de->name, 11); |
@@ -753,7 +714,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
753 | eptr[FATDIR_NTRES] = 0; | 714 | eptr[FATDIR_NTRES] = 0; |
754 | 715 | ||
755 | /* remember where the dir entry is located */ | 716 | /* remember where the dir entry is located */ |
756 | file->dirsector = sec; | 717 | file->dirsector = dir->file.lastsector; |
757 | file->direntry = i/DIR_ENTRY_SIZE; | 718 | file->direntry = i/DIR_ENTRY_SIZE; |
758 | 719 | ||
759 | /* Advance the last_empty_entry marker */ | 720 | /* Advance the last_empty_entry marker */ |
@@ -770,27 +731,23 @@ static int add_dir_entry(struct fat_dir* dir, | |||
770 | { | 731 | { |
771 | /* We must fill in the first entry | 732 | /* We must fill in the first entry |
772 | in the next sector */ | 733 | in the next sector */ |
773 | need_to_update_last_empty_marker = true; | 734 | update_last = true; |
774 | LDEBUGF("need_to_update_last_empty\n"); | 735 | LDEBUGF("update_last = true\n"); |
775 | } | 736 | } |
776 | } | 737 | } |
777 | else | 738 | else |
778 | done = true; | 739 | done = true; |
779 | 740 | ||
780 | err = ata_write_sectors(sec + fat_bpb.startsector,1,buf); | 741 | err=fat_seek(&dir->file, sector-1); |
781 | if (err) | 742 | if (err<0) |
782 | { | 743 | return -5; |
783 | DEBUGF( "add_dir_entry() - " | 744 | err = fat_readwrite(&dir->file, 1, buf, true); |
784 | " Couldn't write dir" | 745 | if (err<1) |
785 | " sector (error code %d)\n", err); | 746 | return -6; |
786 | return -3; | ||
787 | } | ||
788 | break; | 747 | break; |
789 | } | 748 | } |
790 | } | 749 | } |
791 | } | 750 | } |
792 | sec++; | ||
793 | sec_cnt++; | ||
794 | } | 751 | } |
795 | 752 | ||
796 | return 0; | 753 | return 0; |
@@ -885,7 +842,7 @@ static int create_dos_name(unsigned char *name, unsigned char *newname) | |||
885 | return 0; | 842 | return 0; |
886 | } | 843 | } |
887 | 844 | ||
888 | static void update_dir_entry( struct fat_file* file, int size ) | 845 | static int update_file_size( struct fat_file* file, int size ) |
889 | { | 846 | { |
890 | unsigned char buf[SECTOR_SIZE]; | 847 | unsigned char buf[SECTOR_SIZE]; |
891 | int sector = file->dirsector + fat_bpb.startsector; | 848 | int sector = file->dirsector + fat_bpb.startsector; |
@@ -894,21 +851,21 @@ static void update_dir_entry( struct fat_file* file, int size ) | |||
894 | unsigned short* clusptr; | 851 | unsigned short* clusptr; |
895 | int err; | 852 | int err; |
896 | 853 | ||
897 | LDEBUGF("update_dir_entry(cluster:%x entry:%d sector:%x size:%d)\n", | 854 | LDEBUGF("update_file_size(cluster:%x entry:%d sector:%x size:%d)\n", |
898 | file->firstcluster,file->direntry,sector,size); | 855 | file->firstcluster,file->direntry,sector,size); |
899 | 856 | ||
900 | if ( file->direntry >= (SECTOR_SIZE / DIR_ENTRY_SIZE) ) | 857 | if ( file->direntry >= DIR_ENTRIES_PER_SECTOR ) |
901 | panicf("update_dir_entry(): Illegal entry %d!\n",file->direntry); | 858 | panicf("update_file_size(): Illegal entry %d!\n",file->direntry); |
902 | 859 | ||
903 | if ( file->direntry < 0 ) | 860 | if ( file->direntry < 0 ) |
904 | panicf("update_dir_entry(): Illegal entry %d!\n",file->direntry); | 861 | panicf("update_file_size(): Illegal entry %d!\n",file->direntry); |
905 | 862 | ||
906 | err = ata_read_sectors(sector, 1, buf); | 863 | err = ata_read_sectors(sector, 1, buf); |
907 | if (err) | 864 | if (err) |
908 | { | 865 | { |
909 | DEBUGF( "update_dir_entry() - Couldn't read dir sector %d" | 866 | DEBUGF( "update_file_size() - Couldn't read dir sector %d" |
910 | " (error code %d)\n", sector, err); | 867 | " (error code %d)\n", sector, err); |
911 | return; | 868 | return -1; |
912 | } | 869 | } |
913 | 870 | ||
914 | if ( size == -1 ) { | 871 | if ( size == -1 ) { |
@@ -931,8 +888,10 @@ static void update_dir_entry( struct fat_file* file, int size ) | |||
931 | { | 888 | { |
932 | DEBUGF( "update_file_size() - Couldn't write dir sector %d" | 889 | DEBUGF( "update_file_size() - Couldn't write dir sector %d" |
933 | " (error code %d)\n", sector, err); | 890 | " (error code %d)\n", sector, err); |
934 | return; | 891 | return -2; |
935 | } | 892 | } |
893 | |||
894 | return 0; | ||
936 | } | 895 | } |
937 | 896 | ||
938 | static int parse_direntry(struct fat_direntry *de, unsigned char *buf) | 897 | static int parse_direntry(struct fat_direntry *de, unsigned char *buf) |
@@ -968,10 +927,13 @@ int fat_open(unsigned int startcluster, | |||
968 | file->lastcluster = startcluster; | 927 | file->lastcluster = startcluster; |
969 | file->lastsector = 0; | 928 | file->lastsector = 0; |
970 | file->sectornum = 0; | 929 | file->sectornum = 0; |
930 | file->eof = false; | ||
971 | 931 | ||
972 | /* remember where the file's dir entry is located */ | 932 | /* remember where the file's dir entry is located */ |
973 | file->dirsector = dir->cached_sec; | 933 | if ( dir ) { |
974 | file->direntry = dir->entry - 1; | 934 | file->dirsector = dir->cached_sec; |
935 | file->direntry = dir->entry - 1; | ||
936 | } | ||
975 | LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry); | 937 | LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry); |
976 | return 0; | 938 | return 0; |
977 | } | 939 | } |
@@ -1001,6 +963,7 @@ int fat_create_file(char* name, | |||
1001 | file->lastcluster = 0; | 963 | file->lastcluster = 0; |
1002 | file->lastsector = 0; | 964 | file->lastsector = 0; |
1003 | file->sectornum = 0; | 965 | file->sectornum = 0; |
966 | file->eof = false; | ||
1004 | } | 967 | } |
1005 | 968 | ||
1006 | return err; | 969 | return err; |
@@ -1036,7 +999,9 @@ int fat_closewrite(struct fat_file *file, int size) | |||
1036 | } | 999 | } |
1037 | 1000 | ||
1038 | if (file->dirsector) | 1001 | if (file->dirsector) |
1039 | update_dir_entry(file, size); | 1002 | if (update_file_size(file, size) < 0) |
1003 | return -1; | ||
1004 | |||
1040 | flush_fat(); | 1005 | flush_fat(); |
1041 | 1006 | ||
1042 | #ifdef TEST_FAT | 1007 | #ifdef TEST_FAT |
@@ -1072,7 +1037,7 @@ int fat_remove(struct fat_file* file) | |||
1072 | update_fat_entry(last,0); | 1037 | update_fat_entry(last,0); |
1073 | last = next; | 1038 | last = next; |
1074 | } | 1039 | } |
1075 | update_dir_entry(file, -1); | 1040 | update_file_size(file, -1); |
1076 | file->dirsector = 0; | 1041 | file->dirsector = 0; |
1077 | file->firstcluster = 0; | 1042 | file->firstcluster = 0; |
1078 | 1043 | ||
@@ -1151,13 +1116,16 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1151 | int cluster = file->lastcluster; | 1116 | int cluster = file->lastcluster; |
1152 | int sector = file->lastsector; | 1117 | int sector = file->lastsector; |
1153 | int numsec = file->sectornum; | 1118 | int numsec = file->sectornum; |
1119 | bool eof = file->eof; | ||
1154 | int first=0, last=0; | 1120 | int first=0, last=0; |
1155 | int i; | 1121 | int i; |
1156 | 1122 | ||
1157 | LDEBUGF( "fat_readwrite(file:%x,count:0x%x,buf:%x,%s)\n", | 1123 | LDEBUGF( "fat_readwrite(file:%x,count:0x%x,buf:%x,%s)\n", |
1158 | cluster,sectorcount,buf,write?"write":"read"); | 1124 | cluster,sectorcount,buf,write?"write":"read"); |
1159 | LDEBUGF( "fat_readwrite: sec=%x numsec=%d\n", sector,numsec); | 1125 | LDEBUGF( "fat_readwrite: sec=%x numsec=%d eof=%d\n", |
1160 | if ( sector == -1 ) | 1126 | sector,numsec, eof?1:0); |
1127 | |||
1128 | if ( eof && !write) | ||
1161 | return 0; | 1129 | return 0; |
1162 | 1130 | ||
1163 | /* find sequential sectors and write them all at once */ | 1131 | /* find sequential sectors and write them all at once */ |
@@ -1172,13 +1140,15 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1172 | sector = cluster2sec(cluster); | 1140 | sector = cluster2sec(cluster); |
1173 | } | 1141 | } |
1174 | if (!cluster) { | 1142 | if (!cluster) { |
1175 | sector = -1; | 1143 | eof = true; |
1176 | if ( write ) { | 1144 | if ( write ) { |
1177 | /* set file->lastcluster to last available cluster, | 1145 | /* remember last cluster, in case |
1178 | so we can terminate the file in closewrite() */ | 1146 | we want to append to the file */ |
1179 | cluster = oldcluster; | 1147 | cluster = oldcluster; |
1180 | } | 1148 | } |
1181 | } | 1149 | } |
1150 | else | ||
1151 | eof = false; | ||
1182 | numsec=1; | 1152 | numsec=1; |
1183 | } | 1153 | } |
1184 | else { | 1154 | else { |
@@ -1204,11 +1174,13 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1204 | first = sector; | 1174 | first = sector; |
1205 | } | 1175 | } |
1206 | 1176 | ||
1207 | if (i == sectorcount-1) { /* last sector requested */ | 1177 | if ((i == sectorcount-1) && /* last sector requested */ |
1178 | (!eof)) | ||
1179 | { | ||
1208 | int count = sector - first + 1; | 1180 | int count = sector - first + 1; |
1209 | if (!transfer( first + fat_bpb.startsector, | 1181 | if (!transfer( first + fat_bpb.startsector, |
1210 | count, buf, write )) | 1182 | count, buf, write )) |
1211 | return -2; | 1183 | return -2; |
1212 | } | 1184 | } |
1213 | 1185 | ||
1214 | last = sector; | 1186 | last = sector; |
@@ -1217,9 +1189,10 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1217 | file->lastcluster = cluster; | 1189 | file->lastcluster = cluster; |
1218 | file->lastsector = sector; | 1190 | file->lastsector = sector; |
1219 | file->sectornum = numsec; | 1191 | file->sectornum = numsec; |
1192 | file->eof = eof; | ||
1220 | 1193 | ||
1221 | /* if eof, don't report last block as read/written */ | 1194 | /* if eof, don't report last block as read/written */ |
1222 | if (sector == -1) | 1195 | if (eof) |
1223 | i--; | 1196 | i--; |
1224 | 1197 | ||
1225 | return i; | 1198 | return i; |
@@ -1231,29 +1204,31 @@ int fat_seek(struct fat_file *file, unsigned int seeksector ) | |||
1231 | int cluster = file->firstcluster; | 1204 | int cluster = file->firstcluster; |
1232 | int i; | 1205 | int i; |
1233 | 1206 | ||
1207 | file->eof = false; | ||
1234 | if (seeksector) { | 1208 | if (seeksector) { |
1235 | /* we need to find the sector BEFORE the requested, since | 1209 | /* we need to find the sector BEFORE the requested, since |
1236 | the file struct stores the last accessed sector */ | 1210 | the file struct stores the last accessed sector */ |
1237 | seeksector--; | 1211 | seeksector--; |
1238 | clusternum = seeksector / fat_bpb.bpb_secperclus; | 1212 | clusternum = seeksector / fat_bpb.bpb_secperclus; |
1239 | sectornum = seeksector % fat_bpb.bpb_secperclus; | 1213 | sectornum = seeksector % fat_bpb.bpb_secperclus; |
1214 | |||
1240 | 1215 | ||
1241 | for (i=0; i<clusternum; i++) { | 1216 | for (i=0; i<clusternum; i++) { |
1242 | cluster = get_next_cluster(cluster); | 1217 | cluster = get_next_cluster(cluster); |
1243 | if (!cluster) { | 1218 | if (!cluster) { |
1244 | sector = -1; | 1219 | DEBUGF("Seeking beyond the end of the file!\n"); |
1245 | break; | 1220 | return -1; |
1246 | } | 1221 | } |
1247 | } | 1222 | } |
1248 | 1223 | ||
1249 | if ( sector > -1 ) | 1224 | sector = cluster2sec(cluster) + sectornum; |
1250 | sector = cluster2sec(cluster) + sectornum; | ||
1251 | } | 1225 | } |
1252 | else | 1226 | else { |
1253 | sectornum = -1; | 1227 | sectornum = -1; |
1228 | } | ||
1254 | 1229 | ||
1255 | LDEBUGF("fat_seek(%x) == %x, %x, %x\n", | 1230 | LDEBUGF("fat_seek(%x, %x) == %x, %x, %x\n", |
1256 | seeksector, cluster, sector, sectornum); | 1231 | file->firstcluster, seeksector, cluster, sector, sectornum); |
1257 | 1232 | ||
1258 | file->lastcluster = cluster; | 1233 | file->lastcluster = cluster; |
1259 | file->lastsector = sector; | 1234 | file->lastsector = sector; |
@@ -1263,30 +1238,25 @@ int fat_seek(struct fat_file *file, unsigned int seeksector ) | |||
1263 | 1238 | ||
1264 | int fat_opendir(struct fat_dir *dir, unsigned int startcluster) | 1239 | int fat_opendir(struct fat_dir *dir, unsigned int startcluster) |
1265 | { | 1240 | { |
1266 | int is_rootdir = (startcluster == 0); | ||
1267 | unsigned int sec; | ||
1268 | int err; | 1241 | int err; |
1269 | 1242 | ||
1270 | if(is_rootdir) | 1243 | if (startcluster == 0) |
1271 | { | 1244 | startcluster = sec2cluster(fat_bpb.rootdirsector); |
1272 | sec = fat_bpb.rootdirsector; | ||
1273 | } | ||
1274 | else | ||
1275 | { | ||
1276 | sec = first_sector_of_cluster(startcluster); | ||
1277 | } | ||
1278 | 1245 | ||
1279 | /* Read the first sector in the current dir */ | 1246 | err = fat_open(startcluster, &dir->file, NULL); |
1280 | err = ata_read_sectors(sec + fat_bpb.startsector,1,dir->cached_buf); | ||
1281 | if(err) | 1247 | if(err) |
1282 | { | 1248 | { |
1283 | DEBUGF( "fat_opendir() - Couldn't read dir sector" | 1249 | DEBUGF( "fat_opendir() - Couldn't open dir" |
1284 | " (error code %d)\n", err); | 1250 | " (error code %d)\n", err); |
1285 | return -1; | 1251 | return -1; |
1286 | } | 1252 | } |
1287 | 1253 | ||
1254 | err = fat_readwrite(&dir->file, 1, dir->cached_buf, false); | ||
1255 | if (err<1) | ||
1256 | return -2; | ||
1257 | |||
1288 | dir->entry = 0; | 1258 | dir->entry = 0; |
1289 | dir->cached_sec = sec; | 1259 | dir->cached_sec = dir->file.lastsector; |
1290 | dir->num_sec = 0; | 1260 | dir->num_sec = 0; |
1291 | dir->startcluster = startcluster; | 1261 | dir->startcluster = startcluster; |
1292 | 1262 | ||
@@ -1383,55 +1353,25 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1383 | memcpy( lastsector, dir->cached_buf, SECTOR_SIZE ); | 1353 | memcpy( lastsector, dir->cached_buf, SECTOR_SIZE ); |
1384 | sectoridx += SECTOR_SIZE; | 1354 | sectoridx += SECTOR_SIZE; |
1385 | 1355 | ||
1386 | /* Next sector? */ | 1356 | if ( i < SECTOR_SIZE/DIR_ENTRY_SIZE ) { |
1387 | if (i < SECTOR_SIZE / DIR_ENTRY_SIZE) | ||
1388 | { | ||
1389 | i++; | 1357 | i++; |
1390 | } | 1358 | } |
1391 | else | 1359 | else { |
1392 | { | 1360 | err = fat_readwrite(&dir->file, 1, dir->cached_buf, false); |
1393 | dir->num_sec++; | 1361 | if (err==0) { |
1394 | 1362 | /* eof */ | |
1395 | /* Do we need to advance one cluster? */ | 1363 | entry->name[0] = 0; |
1396 | if (dir->num_sec < fat_bpb.bpb_secperclus) | 1364 | return 0; |
1397 | { | ||
1398 | dir->cached_sec++; | ||
1399 | } | ||
1400 | else | ||
1401 | { | ||
1402 | int cluster = sec2cluster(dir->cached_sec); | ||
1403 | if ( cluster < 0 ) { | ||
1404 | DEBUGF("sec2cluster failed\n"); | ||
1405 | return -1; | ||
1406 | } | ||
1407 | dir->num_sec = 0; | ||
1408 | cluster = get_next_cluster( cluster ); | ||
1409 | if (!cluster) | ||
1410 | { | ||
1411 | DEBUGF("End of cluster chain.\n"); | ||
1412 | return -2; | ||
1413 | } | ||
1414 | dir->cached_sec = cluster2sec(cluster); | ||
1415 | if ( dir->cached_sec < 0 ) | ||
1416 | { | ||
1417 | DEBUGF("Invalid cluster: %d\n",cluster); | ||
1418 | return -3; | ||
1419 | } | ||
1420 | |||
1421 | } | 1365 | } |
1422 | 1366 | if (err<0) { | |
1423 | /* Read the next sector */ | 1367 | DEBUGF( "fat_getnext() - Couldn't read dir" |
1424 | err = ata_read_sectors(dir->cached_sec + fat_bpb.startsector, 1, | ||
1425 | dir->cached_buf); | ||
1426 | if (err) | ||
1427 | { | ||
1428 | DEBUGF( "fat_getnext() - Couldn't read dir sector" | ||
1429 | " (error code %d)\n", err); | 1368 | " (error code %d)\n", err); |
1430 | return -4; | 1369 | return -1; |
1431 | } | 1370 | } |
1432 | |||
1433 | i = 0; | 1371 | i = 0; |
1372 | dir->cached_sec = dir->file.lastsector; | ||
1434 | } | 1373 | } |
1374 | |||
1435 | dir->entry = i; | 1375 | dir->entry = i; |
1436 | } | 1376 | } |
1437 | return 0; | 1377 | return 0; |
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index 8ef2982279..4e5397f806 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h | |||
@@ -54,6 +54,7 @@ struct fat_file | |||
54 | int sectornum; /* sector number in this cluster */ | 54 | int sectornum; /* sector number in this cluster */ |
55 | int dirsector; /* sector where the dir entry is located */ | 55 | int dirsector; /* sector where the dir entry is located */ |
56 | int direntry; /* dir entry index in sector */ | 56 | int direntry; /* dir entry index in sector */ |
57 | bool eof; | ||
57 | }; | 58 | }; |
58 | 59 | ||
59 | struct fat_dir | 60 | struct fat_dir |
@@ -63,6 +64,7 @@ struct fat_dir | |||
63 | int num_sec; | 64 | int num_sec; |
64 | unsigned char cached_buf[SECTOR_SIZE]; | 65 | unsigned char cached_buf[SECTOR_SIZE]; |
65 | int startcluster; | 66 | int startcluster; |
67 | struct fat_file file; | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | 70 | ||