diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-10-31 16:09:28 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-10-31 16:09:28 +0000 |
commit | a5e77d8f943e602c56036f0f21b60b7f442a3976 (patch) | |
tree | 324101cf4060f4f06bd522bd49d4f57469a6dad3 /firmware/drivers | |
parent | 3bf2f7858188c222abde85643ce980963dc7e4c9 (diff) | |
download | rockbox-a5e77d8f943e602c56036f0f21b60b7f442a3976.tar.gz rockbox-a5e77d8f943e602c56036f0f21b60b7f442a3976.zip |
Fat writing update. File creation now works, though still only short filenames.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2790 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/fat.c | 217 | ||||
-rw-r--r-- | firmware/drivers/fat.h | 19 |
2 files changed, 158 insertions, 78 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 40f9c47fa7..4c3e410c1a 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -455,11 +455,13 @@ static int update_fat_entry(unsigned int entry, unsigned int val) | |||
455 | 455 | ||
456 | LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); | 456 | LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); |
457 | 457 | ||
458 | #ifdef TEST_FAT | ||
458 | if (entry==val) | 459 | if (entry==val) |
459 | panicf("Creating FAT loop: %x,%x\n",entry,val); | 460 | panicf("Creating FAT loop: %x,%x\n",entry,val); |
460 | 461 | ||
461 | if ( entry < 2 ) | 462 | if ( entry < 2 ) |
462 | panicf("Updating reserved FAT entry %d.\n",entry); | 463 | panicf("Updating reserved FAT entry %d.\n",entry); |
464 | #endif | ||
463 | 465 | ||
464 | sec = cache_fat_sector(sector); | 466 | sec = cache_fat_sector(sector); |
465 | if (!sec) | 467 | if (!sec) |
@@ -636,6 +638,12 @@ static int add_dir_entry(struct fat_dir* dir, | |||
636 | if (sec_cnt >= fat_bpb.bpb_secperclus) | 638 | if (sec_cnt >= fat_bpb.bpb_secperclus) |
637 | { | 639 | { |
638 | int oldcluster; | 640 | int oldcluster; |
641 | |||
642 | /* we're not adding a whole new sector | ||
643 | just for the end-of-dir marker */ | ||
644 | if ( need_to_update_last_empty_marker ) | ||
645 | break; | ||
646 | |||
639 | if (!currdir) | 647 | if (!currdir) |
640 | currdir = sec2cluster(fat_bpb.rootdirsector); | 648 | currdir = sec2cluster(fat_bpb.rootdirsector); |
641 | oldcluster = currdir; | 649 | oldcluster = currdir; |
@@ -647,17 +655,35 @@ static int add_dir_entry(struct fat_dir* dir, | |||
647 | { | 655 | { |
648 | /* end of dir, add new cluster */ | 656 | /* end of dir, add new cluster */ |
649 | LDEBUGF("Adding cluster to dir\n"); | 657 | LDEBUGF("Adding cluster to dir\n"); |
650 | currdir = find_free_cluster(fat_bpb.fsinfo.nextfree); | 658 | currdir = find_free_cluster(oldcluster+1); |
651 | if (!currdir) { | 659 | if (!currdir) { |
652 | DEBUGF("add_dir_entry(): Disk full!\n"); | 660 | DEBUGF("add_dir_entry(): Disk full!\n"); |
653 | return -1; | 661 | return -1; |
654 | } | 662 | } |
655 | update_fat_entry(oldcluster, currdir); | 663 | update_fat_entry(oldcluster, currdir); |
664 | update_fat_entry(currdir, FAT_EOF_MARK); | ||
656 | new = true; | 665 | new = true; |
657 | memset(buf, 0, sizeof buf); | 666 | memset(buf, 0, sizeof buf); |
667 | |||
668 | /* clear remaining sectors in this cluster */ | ||
669 | if (fat_bpb.bpb_secperclus > 1) { | ||
670 | int i; | ||
671 | sec = cluster2sec(currdir); | ||
672 | for (i=1; i<fat_bpb.bpb_secperclus; i++ ) { | ||
673 | err = ata_write_sectors(sec + fat_bpb.startsector + i, | ||
674 | 1, buf); | ||
675 | if (err) { | ||
676 | DEBUGF( "add_dir_entry() - " | ||
677 | " Couldn't write dir" | ||
678 | " sector (error code %d)\n", err); | ||
679 | return -3; | ||
680 | } | ||
681 | } | ||
682 | } | ||
658 | } | 683 | } |
659 | LDEBUGF("new cluster is %x\n", currdir); | 684 | LDEBUGF("new cluster is %x\n", currdir); |
660 | sec = cluster2sec(currdir); | 685 | sec = cluster2sec(currdir); |
686 | sec_cnt = 0; | ||
661 | } | 687 | } |
662 | 688 | ||
663 | if (!new) { | 689 | if (!new) { |
@@ -714,6 +740,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
714 | /* We must fill in the first entry | 740 | /* We must fill in the first entry |
715 | in the next sector */ | 741 | in the next sector */ |
716 | need_to_update_last_empty_marker = true; | 742 | need_to_update_last_empty_marker = true; |
743 | LDEBUGF("need_to_update_last_empty\n"); | ||
717 | } | 744 | } |
718 | } | 745 | } |
719 | else | 746 | else |
@@ -907,13 +934,13 @@ int fat_open(unsigned int startcluster, | |||
907 | { | 934 | { |
908 | file->firstcluster = startcluster; | 935 | file->firstcluster = startcluster; |
909 | file->lastcluster = startcluster; | 936 | file->lastcluster = startcluster; |
910 | file->lastsector = cluster2sec(startcluster); | 937 | file->lastsector = 0; |
911 | file->sectornum = 0; | 938 | file->sectornum = 0; |
912 | 939 | ||
913 | /* remember where the file's dir entry is located */ | 940 | /* remember where the file's dir entry is located */ |
914 | file->dirsector = dir->cached_sec; | 941 | file->dirsector = dir->cached_sec; |
915 | file->direntry = (dir->entry % DIR_ENTRIES_PER_SECTOR) - 1; | 942 | file->direntry = (dir->entry % DIR_ENTRIES_PER_SECTOR) - 1; |
916 | LDEBUGF("fat_open: entry %d\n",file->direntry); | 943 | LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry); |
917 | return 0; | 944 | return 0; |
918 | } | 945 | } |
919 | 946 | ||
@@ -952,7 +979,7 @@ int fat_closewrite(struct fat_file *file, int size) | |||
952 | int next, last = file->lastcluster; | 979 | int next, last = file->lastcluster; |
953 | int endcluster = last; | 980 | int endcluster = last; |
954 | 981 | ||
955 | LDEBUGF("fat_closewrite()\n"); | 982 | LDEBUGF("fat_closewrite(%d)\n",size); |
956 | 983 | ||
957 | last = get_next_cluster(last); | 984 | last = get_next_cluster(last); |
958 | while ( last && last != FAT_EOF_MARK ) { | 985 | while ( last && last != FAT_EOF_MARK ) { |
@@ -961,10 +988,32 @@ int fat_closewrite(struct fat_file *file, int size) | |||
961 | last = next; | 988 | last = next; |
962 | } | 989 | } |
963 | 990 | ||
964 | update_fat_entry(endcluster, FAT_EOF_MARK); | 991 | if ( !size ) { |
992 | /* empty file */ | ||
993 | update_fat_entry(file->firstcluster, 0); | ||
994 | file->firstcluster = 0; | ||
995 | } | ||
996 | else | ||
997 | update_fat_entry(endcluster, FAT_EOF_MARK); | ||
965 | update_dir_entry(file, size); | 998 | update_dir_entry(file, size); |
966 | flush_fat(); | 999 | flush_fat(); |
967 | 1000 | ||
1001 | #ifdef TEST_FAT | ||
1002 | { | ||
1003 | /* debug */ | ||
1004 | int count = 0; | ||
1005 | int len; | ||
1006 | for ( next = file->firstcluster; next; | ||
1007 | next = get_next_cluster(next) ) | ||
1008 | LDEBUGF("cluster %d: %x\n", count++, next); | ||
1009 | len = count * fat_bpb.bpb_secperclus * SECTOR_SIZE; | ||
1010 | LDEBUGF("File is %d clusters (chainlen=%d, size=%d)\n", | ||
1011 | count, len, size ); | ||
1012 | if ( len > size + fat_bpb.bpb_secperclus * SECTOR_SIZE) | ||
1013 | panicf("Cluster chain is too long\n"); | ||
1014 | } | ||
1015 | #endif | ||
1016 | |||
968 | return 0; | 1017 | return 0; |
969 | } | 1018 | } |
970 | 1019 | ||
@@ -999,33 +1048,41 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf ) | |||
999 | if ( sector == -1 ) | 1048 | if ( sector == -1 ) |
1000 | return 0; | 1049 | return 0; |
1001 | 1050 | ||
1002 | first = last = sector; | ||
1003 | |||
1004 | /* find sequential sectors and read/write them all at once */ | 1051 | /* find sequential sectors and read/write them all at once */ |
1005 | for (i=0; i<sectorcount && sector>=0; i++ ) { | 1052 | for (i=0; i<sectorcount && sector>=0; i++ ) { |
1006 | numsec++; | 1053 | numsec++; |
1007 | if ( numsec >= fat_bpb.bpb_secperclus ) { | 1054 | if ( numsec > fat_bpb.bpb_secperclus ) { |
1008 | cluster = get_next_cluster(cluster); | 1055 | cluster = get_next_cluster(cluster); |
1009 | if (!cluster) { | 1056 | if (!cluster) { |
1010 | /* reading past end-of-file */ | 1057 | /* reading past end-of-file */ |
1011 | sector = -1; | 1058 | sector = -1; |
1012 | } | 1059 | } |
1013 | 1060 | ||
1014 | if (cluster) { | 1061 | if (cluster) { |
1015 | sector = cluster2sec(cluster); | 1062 | sector = cluster2sec(cluster); |
1016 | LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector); | 1063 | LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector); |
1017 | if (sector<0) | 1064 | if (sector<0) |
1018 | return -1; | 1065 | return -1; |
1019 | numsec=0; | 1066 | numsec=1; |
1020 | } | 1067 | } |
1021 | } | 1068 | } |
1022 | else | 1069 | else { |
1023 | sector++; | 1070 | if (sector) |
1024 | 1071 | sector++; | |
1025 | if ( (sector != last+1) || /* not sequential any more? */ | 1072 | else { |
1073 | sector = cluster2sec(file->firstcluster); | ||
1074 | numsec=1; | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1078 | if (!first) | ||
1079 | first = sector; | ||
1080 | |||
1081 | if ( ((sector != first) && (sector != last+1)) || | ||
1082 | /* not sequential any more? */ | ||
1026 | (i == sectorcount-1) || /* last sector requested? */ | 1083 | (i == sectorcount-1) || /* last sector requested? */ |
1027 | (last-first+1 == 256) ) { /* max 256 sectors per ata request */ | 1084 | (sector-first+1 == 256) ) { /* max 256 sectors per ata request */ |
1028 | int count = last - first + 1; | 1085 | int count = sector - first + 1; |
1029 | int start = first + fat_bpb.startsector; | 1086 | int start = first + fat_bpb.startsector; |
1030 | LDEBUGF("s=%x, l=%x, f=%x, i=%d\n",sector,last,first,i); | 1087 | LDEBUGF("s=%x, l=%x, f=%x, i=%d\n",sector,last,first,i); |
1031 | err = ata_read_sectors(start, count, buf); | 1088 | err = ata_read_sectors(start, count, buf); |
@@ -1035,10 +1092,10 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf ) | |||
1035 | return -2; | 1092 | return -2; |
1036 | } | 1093 | } |
1037 | ((char*)buf) += count * SECTOR_SIZE; | 1094 | ((char*)buf) += count * SECTOR_SIZE; |
1038 | first = sector; | 1095 | first = 0; |
1039 | } | 1096 | } |
1040 | last = sector; | 1097 | last = sector; |
1041 | } | 1098 | } |
1042 | 1099 | ||
1043 | file->lastcluster = cluster; | 1100 | file->lastcluster = cluster; |
1044 | file->lastsector = sector; | 1101 | file->lastsector = sector; |
@@ -1047,7 +1104,41 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf ) | |||
1047 | return sectorcount; | 1104 | return sectorcount; |
1048 | } | 1105 | } |
1049 | 1106 | ||
1050 | int fat_write( struct fat_file *file, int sectorcount, void* buf ) | 1107 | int next_write_cluster(struct fat_file* file, int oldcluster, int* newsector) |
1108 | { | ||
1109 | int cluster; | ||
1110 | int sector; | ||
1111 | |||
1112 | LDEBUGF("next_write_cluster(%x,%x)\n",file->firstcluster, oldcluster); | ||
1113 | |||
1114 | cluster = get_next_cluster(oldcluster); | ||
1115 | if (!cluster) { | ||
1116 | if (oldcluster) | ||
1117 | cluster = find_free_cluster(oldcluster+1); | ||
1118 | else | ||
1119 | cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); | ||
1120 | |||
1121 | if (cluster) { | ||
1122 | if (oldcluster) | ||
1123 | update_fat_entry(oldcluster, cluster); | ||
1124 | else | ||
1125 | file->firstcluster = cluster; | ||
1126 | } | ||
1127 | else { | ||
1128 | DEBUGF("next_write_sector(): Disk full!\n"); | ||
1129 | return 0; | ||
1130 | } | ||
1131 | } | ||
1132 | sector = cluster2sec(cluster); | ||
1133 | if (sector<0) | ||
1134 | return 0; | ||
1135 | |||
1136 | *newsector = sector; | ||
1137 | return cluster; | ||
1138 | } | ||
1139 | |||
1140 | int fat_readwrite( struct fat_file *file, int sectorcount, | ||
1141 | void* buf, bool write ) | ||
1051 | { | 1142 | { |
1052 | int cluster = file->lastcluster; | 1143 | int cluster = file->lastcluster; |
1053 | int sector = file->lastsector; | 1144 | int sector = file->lastsector; |
@@ -1062,53 +1153,50 @@ int fat_write( struct fat_file *file, int sectorcount, void* buf ) | |||
1062 | return 0; | 1153 | return 0; |
1063 | 1154 | ||
1064 | /* find sequential sectors and write them all at once */ | 1155 | /* find sequential sectors and write them all at once */ |
1065 | for (i=0; i<sectorcount && sector>=0; i++ ) { | 1156 | for (i=0; i<sectorcount; i++ ) { |
1066 | numsec++; | 1157 | numsec++; |
1067 | 1158 | if ( numsec > fat_bpb.bpb_secperclus || !cluster ) { | |
1068 | /* find a new cluster */ | 1159 | if (write) |
1069 | if ( numsec >= fat_bpb.bpb_secperclus || !cluster) { | 1160 | cluster = next_write_cluster(file, cluster, §or); |
1070 | int oldcluster = cluster; | 1161 | else { |
1071 | cluster = get_next_cluster(cluster); | 1162 | cluster = get_next_cluster(cluster); |
1072 | if (!cluster) { | 1163 | sector = cluster2sec(cluster); |
1073 | if (!oldcluster) | 1164 | } |
1074 | cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); | 1165 | if (!cluster) |
1075 | else | 1166 | sector = -1; |
1076 | cluster = find_free_cluster(oldcluster+1); | 1167 | numsec=1; |
1077 | 1168 | } | |
1078 | if (cluster) { | 1169 | else { |
1079 | if ( !oldcluster ) | 1170 | if (sector) |
1080 | file->firstcluster = cluster; | 1171 | sector++; |
1081 | else | 1172 | else { |
1082 | update_fat_entry(oldcluster, cluster); | 1173 | sector = cluster2sec(file->firstcluster); |
1083 | } | 1174 | numsec=1; |
1084 | else { | ||
1085 | sector = -1; | ||
1086 | DEBUGF("fat_write(): Disk full!\n"); | ||
1087 | } | ||
1088 | } | 1175 | } |
1176 | } | ||
1089 | 1177 | ||
1090 | if (cluster) { | 1178 | if (!first) |
1091 | sector = cluster2sec(cluster); | 1179 | first = sector; |
1092 | LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector); | ||
1093 | if (sector<0) | ||
1094 | return -1; | ||
1095 | numsec=0; | ||
1096 | 1180 | ||
1097 | if (!oldcluster) | 1181 | if ( ((sector != first) && (sector != last+1)) || /* not sequential */ |
1098 | first = last = sector; | 1182 | (i == sectorcount-1) || /* last sector requested */ |
1183 | (sector-first+1 == 256) ) { /* max 256 sectors per ata request */ | ||
1184 | int count = sector - first + 1; | ||
1185 | int start = first + fat_bpb.startsector; | ||
1186 | LDEBUGF("s=%x, l=%x, f=%x, i=%d\n",sector,last,first,i); | ||
1187 | if (write) | ||
1188 | err = ata_write_sectors(start, count, buf); | ||
1189 | else | ||
1190 | err = ata_read_sectors(start, count, buf); | ||
1191 | if (err) { | ||
1192 | DEBUGF( "fat_readwrite() - Couldn't read sector %d" | ||
1193 | " (error code %d)\n", sector,err); | ||
1194 | return -2; | ||
1099 | } | 1195 | } |
1196 | ((char*)buf) += count * SECTOR_SIZE; | ||
1197 | first = 0; | ||
1100 | } | 1198 | } |
1101 | else | 1199 | last = sector; |
1102 | sector++; | ||
1103 | |||
1104 | /* we start simple: one sector at a time */ | ||
1105 | err = ata_write_sectors(sector, 1, buf); | ||
1106 | if (err) { | ||
1107 | DEBUGF( "fat_write() - Couldn't write sector %d" | ||
1108 | " (error code %d)\n", sector,err); | ||
1109 | return -2; | ||
1110 | } | ||
1111 | ((char*)buf) += SECTOR_SIZE; | ||
1112 | } | 1200 | } |
1113 | 1201 | ||
1114 | file->lastcluster = cluster; | 1202 | file->lastcluster = cluster; |
@@ -1118,15 +1206,6 @@ int fat_write( struct fat_file *file, int sectorcount, void* buf ) | |||
1118 | return sectorcount; | 1206 | return sectorcount; |
1119 | } | 1207 | } |
1120 | 1208 | ||
1121 | int fat_readwrite( struct fat_file *file, int sectorcount, | ||
1122 | void* buf, bool write ) | ||
1123 | { | ||
1124 | if (write) | ||
1125 | return fat_write(file, sectorcount, buf); | ||
1126 | else | ||
1127 | return fat_read(file, sectorcount, buf); | ||
1128 | } | ||
1129 | |||
1130 | int fat_seek(struct fat_file *file, int seeksector ) | 1209 | int fat_seek(struct fat_file *file, int seeksector ) |
1131 | { | 1210 | { |
1132 | int cluster = file->firstcluster; | 1211 | int cluster = file->firstcluster; |
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index 1316202a6c..6ed68ad8d8 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h | |||
@@ -46,15 +46,6 @@ struct fat_direntry | |||
46 | #define FAT_ATTR_DIRECTORY 0x10 | 46 | #define FAT_ATTR_DIRECTORY 0x10 |
47 | #define FAT_ATTR_ARCHIVE 0x20 | 47 | #define FAT_ATTR_ARCHIVE 0x20 |
48 | 48 | ||
49 | struct fat_dir | ||
50 | { | ||
51 | int entry; | ||
52 | int cached_sec; | ||
53 | int num_sec; | ||
54 | unsigned char cached_buf[SECTOR_SIZE]; | ||
55 | int startcluster; | ||
56 | }; | ||
57 | |||
58 | struct fat_file | 49 | struct fat_file |
59 | { | 50 | { |
60 | int firstcluster; /* first cluster in file */ | 51 | int firstcluster; /* first cluster in file */ |
@@ -65,6 +56,16 @@ struct fat_file | |||
65 | int direntry; /* dir entry index in sector */ | 56 | int direntry; /* dir entry index in sector */ |
66 | }; | 57 | }; |
67 | 58 | ||
59 | struct fat_dir | ||
60 | { | ||
61 | int entry; | ||
62 | int cached_sec; | ||
63 | int num_sec; | ||
64 | unsigned char cached_buf[SECTOR_SIZE]; | ||
65 | int startcluster; | ||
66 | }; | ||
67 | |||
68 | |||
68 | extern int fat_mount(int startsector); | 69 | extern int fat_mount(int startsector); |
69 | 70 | ||
70 | extern int fat_create_dir(unsigned int currdir, char *name); | 71 | extern int fat_create_dir(unsigned int currdir, char *name); |