summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/fat.c217
-rw-r--r--firmware/drivers/fat.h19
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
1050int fat_write( struct fat_file *file, int sectorcount, void* buf ) 1107int 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
1140int 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, &sector);
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
1121int 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
1130int fat_seek(struct fat_file *file, int seeksector ) 1209int 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
49struct 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
58struct fat_file 49struct 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
59struct 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
68extern int fat_mount(int startsector); 69extern int fat_mount(int startsector);
69 70
70extern int fat_create_dir(unsigned int currdir, char *name); 71extern int fat_create_dir(unsigned int currdir, char *name);