diff options
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r-- | firmware/drivers/fat.c | 175 |
1 files changed, 113 insertions, 62 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 89b322e10a..40f9c47fa7 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -429,14 +429,15 @@ static int find_free_cluster(int startcluster) | |||
429 | int offset = startcluster % CLUSTERS_PER_FAT_SECTOR; | 429 | int offset = startcluster % CLUSTERS_PER_FAT_SECTOR; |
430 | int i; | 430 | int i; |
431 | 431 | ||
432 | for (i = sector; i<fat_bpb.fatsize; i++) { | 432 | for (i = 0; i<fat_bpb.fatsize; i++) { |
433 | int j; | 433 | int j; |
434 | unsigned int* fat = cache_fat_sector(i); | 434 | int nr = (i + sector) % fat_bpb.fatsize; |
435 | unsigned int* fat = cache_fat_sector(nr); | ||
435 | if ( !fat ) | 436 | if ( !fat ) |
436 | break; | 437 | break; |
437 | for (j = offset; j < CLUSTERS_PER_FAT_SECTOR; j++) | 438 | for (j = offset; j < CLUSTERS_PER_FAT_SECTOR; j++) |
438 | if (!(SWAB32(fat[j]) & 0x0fffffff)) { | 439 | if (!(SWAB32(fat[j]) & 0x0fffffff)) { |
439 | int c = i * CLUSTERS_PER_FAT_SECTOR + j; | 440 | int c = nr * CLUSTERS_PER_FAT_SECTOR + j; |
440 | LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); | 441 | LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); |
441 | fat_bpb.fsinfo.nextfree = c; | 442 | fat_bpb.fsinfo.nextfree = c; |
442 | return c; | 443 | return c; |
@@ -472,8 +473,10 @@ static int update_fat_entry(unsigned int entry, unsigned int val) | |||
472 | if (!(SWAB32(sec[offset]) & 0x0fffffff)) | 473 | if (!(SWAB32(sec[offset]) & 0x0fffffff)) |
473 | fat_bpb.fsinfo.freecount--; | 474 | fat_bpb.fsinfo.freecount--; |
474 | } | 475 | } |
475 | else | 476 | else { |
476 | fat_bpb.fsinfo.freecount++; | 477 | if (SWAB32(sec[offset]) & 0x0fffffff) |
478 | fat_bpb.fsinfo.freecount++; | ||
479 | } | ||
477 | 480 | ||
478 | /* don't change top 4 bits */ | 481 | /* don't change top 4 bits */ |
479 | sec[offset] &= SWAB32(0xf0000000); | 482 | sec[offset] &= SWAB32(0xf0000000); |
@@ -503,7 +506,6 @@ static int get_next_cluster(unsigned int cluster) | |||
503 | int next_cluster; | 506 | int next_cluster; |
504 | 507 | ||
505 | next_cluster = read_fat_entry(cluster); | 508 | next_cluster = read_fat_entry(cluster); |
506 | LDEBUGF("get_next_cluster(%x) == %x\n",cluster,next_cluster); | ||
507 | 509 | ||
508 | /* is this last cluster in chain? */ | 510 | /* is this last cluster in chain? */ |
509 | if ( next_cluster >= FAT_EOF_MARK ) | 511 | if ( next_cluster >= FAT_EOF_MARK ) |
@@ -630,6 +632,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
630 | 632 | ||
631 | while(!done) | 633 | while(!done) |
632 | { | 634 | { |
635 | bool new = false; | ||
633 | if (sec_cnt >= fat_bpb.bpb_secperclus) | 636 | if (sec_cnt >= fat_bpb.bpb_secperclus) |
634 | { | 637 | { |
635 | int oldcluster; | 638 | int oldcluster; |
@@ -646,26 +649,27 @@ static int add_dir_entry(struct fat_dir* dir, | |||
646 | LDEBUGF("Adding cluster to dir\n"); | 649 | LDEBUGF("Adding cluster to dir\n"); |
647 | currdir = find_free_cluster(fat_bpb.fsinfo.nextfree); | 650 | currdir = find_free_cluster(fat_bpb.fsinfo.nextfree); |
648 | if (!currdir) { | 651 | if (!currdir) { |
649 | currdir = find_free_cluster(0); | 652 | DEBUGF("add_dir_entry(): Disk full!\n"); |
650 | if (!currdir) { | 653 | return -1; |
651 | DEBUGF("add_dir_entry(): Disk full!\n"); | ||
652 | return -1; | ||
653 | } | ||
654 | } | 654 | } |
655 | update_fat_entry(oldcluster, currdir); | 655 | update_fat_entry(oldcluster, currdir); |
656 | new = true; | ||
657 | memset(buf, 0, sizeof buf); | ||
656 | } | 658 | } |
657 | LDEBUGF("new cluster is %x\n", currdir); | 659 | LDEBUGF("new cluster is %x\n", currdir); |
658 | sec = cluster2sec(currdir); | 660 | sec = cluster2sec(currdir); |
659 | } | 661 | } |
660 | 662 | ||
661 | LDEBUGF("Reading sector %x...\n", sec); | 663 | if (!new) { |
662 | /* Read the next sector in the current dir */ | 664 | LDEBUGF("Reading sector %x...\n", sec); |
663 | err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); | 665 | /* Read the next sector in the current dir */ |
664 | if (err) | 666 | err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); |
665 | { | 667 | if (err) |
666 | DEBUGF( "add_dir_entry() - Couldn't read dir sector" | 668 | { |
667 | " (error code %d)\n", err); | 669 | DEBUGF( "add_dir_entry() - Couldn't read dir sector" |
668 | return -2; | 670 | " (error code %d)\n", err); |
671 | return -2; | ||
672 | } | ||
669 | } | 673 | } |
670 | 674 | ||
671 | if (need_to_update_last_empty_marker) | 675 | if (need_to_update_last_empty_marker) |
@@ -981,8 +985,7 @@ int fat_remove(struct fat_file* file) | |||
981 | return 0; | 985 | return 0; |
982 | } | 986 | } |
983 | 987 | ||
984 | int fat_readwrite( struct fat_file *file, int sectorcount, | 988 | int fat_read( struct fat_file *file, int sectorcount, void* buf ) |
985 | void* buf, bool write ) | ||
986 | { | 989 | { |
987 | int cluster = file->lastcluster; | 990 | int cluster = file->lastcluster; |
988 | int sector = file->lastsector; | 991 | int sector = file->lastsector; |
@@ -990,48 +993,22 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
990 | int first=0, last=0; | 993 | int first=0, last=0; |
991 | int err, i; | 994 | int err, i; |
992 | 995 | ||
993 | LDEBUGF( "fat_readwrite(file:%x,count:%d,buf:%x,%s)\n", | 996 | LDEBUGF( "fat_read(file:%x,count:%d,buf:%x)\n", |
994 | cluster,sectorcount,buf,write?"write":"read"); | 997 | cluster,sectorcount,buf); |
995 | LDEBUGF( "fat_readwrite: c=%x s=%x n=%d\n", cluster,sector,numsec); | 998 | LDEBUGF( "fat_read: c=%x s=%x n=%d\n", cluster,sector,numsec); |
996 | if ( sector == -1 ) | 999 | if ( sector == -1 ) |
997 | return 0; | 1000 | return 0; |
998 | 1001 | ||
999 | if (!write) | 1002 | first = last = sector; |
1000 | first = last = sector; | ||
1001 | 1003 | ||
1002 | /* find sequential sectors and read/write them all at once */ | 1004 | /* find sequential sectors and read/write them all at once */ |
1003 | for (i=0; i<sectorcount && sector>=0; i++ ) { | 1005 | for (i=0; i<sectorcount && sector>=0; i++ ) { |
1004 | numsec++; | 1006 | numsec++; |
1005 | if ( numsec >= fat_bpb.bpb_secperclus || !cluster) { | 1007 | if ( numsec >= fat_bpb.bpb_secperclus ) { |
1006 | int oldcluster = cluster; | ||
1007 | cluster = get_next_cluster(cluster); | 1008 | cluster = get_next_cluster(cluster); |
1008 | if (!cluster) { | 1009 | if (!cluster) { |
1009 | if ( write ) { | 1010 | /* reading past end-of-file */ |
1010 | if (!oldcluster) /* new file */ | 1011 | sector = -1; |
1011 | cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); | ||
1012 | else /* writing past end-of-file */ | ||
1013 | cluster = find_free_cluster(oldcluster+1); | ||
1014 | if (!cluster) { | ||
1015 | /* no free cluster found after last, | ||
1016 | search from beginning */ | ||
1017 | cluster = find_free_cluster(0); | ||
1018 | if (!cluster) { | ||
1019 | /* no free clusters. disk is full. */ | ||
1020 | sector = -1; | ||
1021 | DEBUGF("fat_readwrite(): Disk full!\n"); | ||
1022 | } | ||
1023 | } | ||
1024 | if ( cluster ) { | ||
1025 | if ( !oldcluster ) | ||
1026 | file->firstcluster = cluster; | ||
1027 | else | ||
1028 | update_fat_entry(oldcluster, cluster); | ||
1029 | } | ||
1030 | } | ||
1031 | else { | ||
1032 | /* reading past end-of-file */ | ||
1033 | sector = -1; | ||
1034 | } | ||
1035 | } | 1012 | } |
1036 | 1013 | ||
1037 | if (cluster) { | 1014 | if (cluster) { |
@@ -1045,21 +1022,15 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1045 | else | 1022 | else |
1046 | sector++; | 1023 | sector++; |
1047 | 1024 | ||
1048 | if (write && !first) | ||
1049 | first = last = sector; | ||
1050 | |||
1051 | if ( (sector != last+1) || /* not sequential any more? */ | 1025 | if ( (sector != last+1) || /* not sequential any more? */ |
1052 | (i == sectorcount-1) || /* last sector requested? */ | 1026 | (i == sectorcount-1) || /* last sector requested? */ |
1053 | (last-first+1 == 256) ) { /* max 256 sectors per ata request */ | 1027 | (last-first+1 == 256) ) { /* max 256 sectors per ata request */ |
1054 | int count = last - first + 1; | 1028 | int count = last - first + 1; |
1055 | int start = first + fat_bpb.startsector; | 1029 | int start = first + fat_bpb.startsector; |
1056 | LDEBUGF("s=%x, l=%x, f=%x, i=%d\n",sector,last,first,i); | 1030 | LDEBUGF("s=%x, l=%x, f=%x, i=%d\n",sector,last,first,i); |
1057 | if (write) | 1031 | err = ata_read_sectors(start, count, buf); |
1058 | err = ata_write_sectors(start, count, buf); | ||
1059 | else | ||
1060 | err = ata_read_sectors(start, count, buf); | ||
1061 | if (err) { | 1032 | if (err) { |
1062 | DEBUGF( "fat_readwrite() - Couldn't read sector %d" | 1033 | DEBUGF( "fat_read() - Couldn't read sector %d" |
1063 | " (error code %d)\n", sector,err); | 1034 | " (error code %d)\n", sector,err); |
1064 | return -2; | 1035 | return -2; |
1065 | } | 1036 | } |
@@ -1076,6 +1047,86 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1076 | return sectorcount; | 1047 | return sectorcount; |
1077 | } | 1048 | } |
1078 | 1049 | ||
1050 | int fat_write( struct fat_file *file, int sectorcount, void* buf ) | ||
1051 | { | ||
1052 | int cluster = file->lastcluster; | ||
1053 | int sector = file->lastsector; | ||
1054 | int numsec = file->sectornum; | ||
1055 | int first=0, last=0; | ||
1056 | int err, i; | ||
1057 | |||
1058 | LDEBUGF( "fat_write(file:%x,count:%d,buf:%x)\n", | ||
1059 | cluster,sectorcount,buf); | ||
1060 | LDEBUGF( "fat_write: c=%x s=%x n=%d\n", cluster,sector,numsec); | ||
1061 | if ( sector == -1 ) | ||
1062 | return 0; | ||
1063 | |||
1064 | /* find sequential sectors and write them all at once */ | ||
1065 | for (i=0; i<sectorcount && sector>=0; i++ ) { | ||
1066 | numsec++; | ||
1067 | |||
1068 | /* find a new cluster */ | ||
1069 | if ( numsec >= fat_bpb.bpb_secperclus || !cluster) { | ||
1070 | int oldcluster = cluster; | ||
1071 | cluster = get_next_cluster(cluster); | ||
1072 | if (!cluster) { | ||
1073 | if (!oldcluster) | ||
1074 | cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); | ||
1075 | else | ||
1076 | cluster = find_free_cluster(oldcluster+1); | ||
1077 | |||
1078 | if (cluster) { | ||
1079 | if ( !oldcluster ) | ||
1080 | file->firstcluster = cluster; | ||
1081 | else | ||
1082 | update_fat_entry(oldcluster, cluster); | ||
1083 | } | ||
1084 | else { | ||
1085 | sector = -1; | ||
1086 | DEBUGF("fat_write(): Disk full!\n"); | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | if (cluster) { | ||
1091 | sector = cluster2sec(cluster); | ||
1092 | LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector); | ||
1093 | if (sector<0) | ||
1094 | return -1; | ||
1095 | numsec=0; | ||
1096 | |||
1097 | if (!oldcluster) | ||
1098 | first = last = sector; | ||
1099 | } | ||
1100 | } | ||
1101 | else | ||
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 | } | ||
1113 | |||
1114 | file->lastcluster = cluster; | ||
1115 | file->lastsector = sector; | ||
1116 | file->sectornum = numsec; | ||
1117 | |||
1118 | return sectorcount; | ||
1119 | } | ||
1120 | |||
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 | |||
1079 | int fat_seek(struct fat_file *file, int seeksector ) | 1130 | int fat_seek(struct fat_file *file, int seeksector ) |
1080 | { | 1131 | { |
1081 | int cluster = file->firstcluster; | 1132 | int cluster = file->firstcluster; |