summaryrefslogtreecommitdiff
path: root/firmware/drivers/fat.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r--firmware/drivers/fat.c159
1 files changed, 90 insertions, 69 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 322ae76a2d..a60a017d3e 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -241,8 +241,7 @@ int fat_mount(int startsector)
241 err = ata_read_sectors(startsector,1,buf); 241 err = ata_read_sectors(startsector,1,buf);
242 if(err) 242 if(err)
243 { 243 {
244 DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", 244 DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", err);
245 err);
246 return -1; 245 return -1;
247 } 246 }
248 247
@@ -325,7 +324,7 @@ int fat_mount(int startsector)
325 if (err) 324 if (err)
326 { 325 {
327 DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", err); 326 DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", err);
328 return -1; 327 return -4;
329 } 328 }
330 fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); 329 fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT);
331 fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); 330 fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE);
@@ -430,8 +429,6 @@ static int find_free_cluster(int startcluster)
430 int offset = startcluster % CLUSTERS_PER_FAT_SECTOR; 429 int offset = startcluster % CLUSTERS_PER_FAT_SECTOR;
431 int i; 430 int i;
432 431
433 LDEBUGF("find_free_cluster(%x)\n",startcluster);
434
435 for (i = sector; i<fat_bpb.fatsize; i++) { 432 for (i = sector; i<fat_bpb.fatsize; i++) {
436 int j; 433 int j;
437 unsigned int* fat = cache_fat_sector(i); 434 unsigned int* fat = cache_fat_sector(i);
@@ -440,15 +437,16 @@ static int find_free_cluster(int startcluster)
440 for (j = offset; j < CLUSTERS_PER_FAT_SECTOR; j++) 437 for (j = offset; j < CLUSTERS_PER_FAT_SECTOR; j++)
441 if (!(SWAB32(fat[j]) & 0x0fffffff)) { 438 if (!(SWAB32(fat[j]) & 0x0fffffff)) {
442 int c = i * CLUSTERS_PER_FAT_SECTOR + j; 439 int c = i * CLUSTERS_PER_FAT_SECTOR + j;
443 LDEBUGF("Found free cluster %x\n",c); 440 LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c);
444 fat_bpb.fsinfo.nextfree = c; 441 fat_bpb.fsinfo.nextfree = c;
445 return c; 442 return c;
446 } 443 }
447 } 444 }
445 LDEBUGF("find_free_cluster(%x) == 0\n",startcluster);
448 return 0; /* 0 is an illegal cluster number */ 446 return 0; /* 0 is an illegal cluster number */
449} 447}
450 448
451static int update_fat_entry(int entry, unsigned int val) 449static int update_fat_entry(unsigned int entry, unsigned int val)
452{ 450{
453 int sector = entry / CLUSTERS_PER_FAT_SECTOR; 451 int sector = entry / CLUSTERS_PER_FAT_SECTOR;
454 int offset = entry % CLUSTERS_PER_FAT_SECTOR; 452 int offset = entry % CLUSTERS_PER_FAT_SECTOR;
@@ -456,6 +454,12 @@ static int update_fat_entry(int entry, unsigned int val)
456 454
457 LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); 455 LDEBUGF("update_fat_entry(%x,%x)\n",entry,val);
458 456
457 if (entry==val)
458 panicf("Creating FAT loop: %x,%x\n",entry,val);
459
460 if ( entry < 2 )
461 panicf("Updating reserved FAT entry %d.\n",entry);
462
459 sec = cache_fat_sector(sector); 463 sec = cache_fat_sector(sector);
460 if (!sec) 464 if (!sec)
461 { 465 {
@@ -465,14 +469,14 @@ static int update_fat_entry(int entry, unsigned int val)
465 fat_cache[sector & FAT_CACHE_MASK].dirty = true; 469 fat_cache[sector & FAT_CACHE_MASK].dirty = true;
466 470
467 if ( val ) { 471 if ( val ) {
468 if (!(sec[offset] & 0x0fffffff)) 472 if (!(SWAB32(sec[offset]) & 0x0fffffff))
469 fat_bpb.fsinfo.freecount--; 473 fat_bpb.fsinfo.freecount--;
470 } 474 }
471 else 475 else
472 fat_bpb.fsinfo.freecount++; 476 fat_bpb.fsinfo.freecount++;
473 477
474 /* don't change top 4 bits */ 478 /* don't change top 4 bits */
475 sec[offset] &= SWAB32(0xf000000); 479 sec[offset] &= SWAB32(0xf0000000);
476 sec[offset] |= SWAB32(val & 0x0fffffff); 480 sec[offset] |= SWAB32(val & 0x0fffffff);
477 481
478 return 0; 482 return 0;
@@ -491,7 +495,7 @@ static int read_fat_entry(int entry)
491 return -1; 495 return -1;
492 } 496 }
493 497
494 return SWAB32(sec[offset]); 498 return SWAB32(sec[offset]) & 0x0fffffff;
495} 499}
496 500
497static int get_next_cluster(unsigned int cluster) 501static int get_next_cluster(unsigned int cluster)
@@ -499,6 +503,7 @@ static int get_next_cluster(unsigned int cluster)
499 int next_cluster; 503 int next_cluster;
500 504
501 next_cluster = read_fat_entry(cluster); 505 next_cluster = read_fat_entry(cluster);
506 LDEBUGF("get_next_cluster(%x) == %x\n",cluster,next_cluster);
502 507
503 /* is this last cluster in chain? */ 508 /* is this last cluster in chain? */
504 if ( next_cluster >= FAT_EOF_MARK ) 509 if ( next_cluster >= FAT_EOF_MARK )
@@ -608,34 +613,37 @@ static int add_dir_entry(struct fat_dir* dir,
608 int i; 613 int i;
609 int err; 614 int err;
610 int sec; 615 int sec;
611 int sec_cnt; 616 int sec_cnt = 0;
612 bool need_to_update_last_empty_marker = false; 617 bool need_to_update_last_empty_marker = false;
613 bool done = false; 618 bool done = false;
614 unsigned char firstbyte; 619 unsigned char firstbyte;
615 int currdir = dir->startcluster; 620 int currdir = dir->startcluster;
616 bool is_rootdir = (currdir == 0); 621 bool is_rootdir = (currdir == 0);
617 622
618 LDEBUGF( "add_dir_entry()\n"); 623 LDEBUGF( "add_dir_entry(%x,%s,%x)\n",
624 dir->startcluster, de->name, file->firstcluster);
619 625
620 if (is_rootdir) 626 if (is_rootdir)
621 sec = fat_bpb.rootdirsector; 627 sec = fat_bpb.rootdirsector;
622 else 628 else
623 sec = first_sector_of_cluster(currdir); 629 sec = first_sector_of_cluster(currdir);
624 630
625 sec_cnt = 0;
626
627 while(!done) 631 while(!done)
628 { 632 {
629 if (sec_cnt >= fat_bpb.bpb_secperclus) 633 if (sec_cnt >= fat_bpb.bpb_secperclus)
630 { 634 {
631 int oldcluster = currdir; 635 int oldcluster;
636 if (!currdir)
637 currdir = sec2cluster(fat_bpb.rootdirsector);
638 oldcluster = currdir;
639
632 /* We have reached the end of this cluster */ 640 /* We have reached the end of this cluster */
633 LDEBUGF("Moving to the next cluster..."); 641 LDEBUGF("Moving to the next cluster...\n");
634 currdir = get_next_cluster(currdir); 642 currdir = get_next_cluster(currdir);
635 LDEBUGF("new cluster is %d\n", currdir);
636
637 if (!currdir) 643 if (!currdir)
638 { 644 {
645 /* end of dir, add new cluster */
646 LDEBUGF("Adding cluster to dir\n");
639 currdir = find_free_cluster(fat_bpb.fsinfo.nextfree); 647 currdir = find_free_cluster(fat_bpb.fsinfo.nextfree);
640 if (!currdir) { 648 if (!currdir) {
641 currdir = find_free_cluster(0); 649 currdir = find_free_cluster(0);
@@ -646,9 +654,11 @@ static int add_dir_entry(struct fat_dir* dir,
646 } 654 }
647 update_fat_entry(oldcluster, currdir); 655 update_fat_entry(oldcluster, currdir);
648 } 656 }
657 LDEBUGF("new cluster is %x\n", currdir);
658 sec = cluster2sec(currdir);
649 } 659 }
650 660
651 LDEBUGF("Reading sector %d...\n", sec); 661 LDEBUGF("Reading sector %x...\n", sec);
652 /* Read the next sector in the current dir */ 662 /* Read the next sector in the current dir */
653 err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); 663 err = ata_read_sectors(sec + fat_bpb.startsector,1,buf);
654 if (err) 664 if (err)
@@ -673,7 +683,7 @@ static int add_dir_entry(struct fat_dir* dir,
673 firstbyte = buf[i]; 683 firstbyte = buf[i];
674 if (firstbyte == 0xe5 || firstbyte == 0) 684 if (firstbyte == 0xe5 || firstbyte == 0)
675 { 685 {
676 LDEBUGF("Found free slot at entry %d in sector %x\n", 686 LDEBUGF("Found free entry %d in sector %x\n",
677 i/DIR_ENTRY_SIZE, sec); 687 i/DIR_ENTRY_SIZE, sec);
678 eptr = &buf[i]; 688 eptr = &buf[i];
679 memset(eptr, 0, DIR_ENTRY_SIZE); 689 memset(eptr, 0, DIR_ENTRY_SIZE);
@@ -681,22 +691,6 @@ static int add_dir_entry(struct fat_dir* dir,
681 eptr[FATDIR_ATTR] = de->attr; 691 eptr[FATDIR_ATTR] = de->attr;
682 eptr[FATDIR_NTRES] = 0; 692 eptr[FATDIR_NTRES] = 0;
683 693
684 eptr[FATDIR_CRTTIMETENTH] = de->crttimetenth;
685 eptr[FATDIR_CRTDATE] = de->crtdate & 0xff;
686 eptr[FATDIR_CRTDATE+1] = de->crtdate >> 8;
687 eptr[FATDIR_CRTTIME] = de->crttime & 0xff;
688 eptr[FATDIR_CRTTIME+1] = de->crttime >> 8;
689
690 eptr[FATDIR_WRTDATE] = de->wrtdate & 0xff;
691 eptr[FATDIR_WRTDATE+1] = de->wrtdate >> 8;
692 eptr[FATDIR_WRTTIME] = de->wrttime & 0xff;
693 eptr[FATDIR_WRTTIME+1] = de->wrttime >> 8;
694
695 eptr[FATDIR_FILESIZE] = de->filesize & 0xff;
696 eptr[FATDIR_FILESIZE+1] = (de->filesize >> 8) & 0xff;
697 eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff;
698 eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff;
699
700 /* remember where the dir entry is located */ 694 /* remember where the dir entry is located */
701 file->dirsector = sec; 695 file->dirsector = sec;
702 file->direntry = i/DIR_ENTRY_SIZE; 696 file->direntry = i/DIR_ENTRY_SIZE;
@@ -853,15 +847,21 @@ static void update_dir_entry( struct fat_file* file, int size )
853 " (error code %d)\n", sector, err); 847 " (error code %d)\n", sector, err);
854 return; 848 return;
855 } 849 }
856
857 clusptr = (short*)(entry + FATDIR_FSTCLUSHI);
858 *clusptr = SWAB16(file->firstcluster >> 16);
859 850
860 clusptr = (short*)(entry + FATDIR_FSTCLUSLO); 851 if ( size == -1 ) {
861 *clusptr = SWAB16(file->firstcluster & 0xffff); 852 /* mark entry deleted */
853 entry[0] = 0xe5;
854 }
855 else {
856 clusptr = (short*)(entry + FATDIR_FSTCLUSHI);
857 *clusptr = SWAB16(file->firstcluster >> 16);
858
859 clusptr = (short*)(entry + FATDIR_FSTCLUSLO);
860 *clusptr = SWAB16(file->firstcluster & 0xffff);
862 861
863 sizeptr = (int*)(entry + FATDIR_FILESIZE); 862 sizeptr = (int*)(entry + FATDIR_FILESIZE);
864 *sizeptr = SWAB32(size); 863 *sizeptr = SWAB32(size);
864 }
865 865
866 err = ata_write_sectors(sector, 1, buf); 866 err = ata_write_sectors(sector, 1, buf);
867 if (err) 867 if (err)
@@ -902,8 +902,8 @@ int fat_open(unsigned int startcluster,
902 struct fat_dir* dir) 902 struct fat_dir* dir)
903{ 903{
904 file->firstcluster = startcluster; 904 file->firstcluster = startcluster;
905 file->nextcluster = startcluster; 905 file->lastcluster = startcluster;
906 file->nextsector = cluster2sec(startcluster); 906 file->lastsector = cluster2sec(startcluster);
907 file->sectornum = 0; 907 file->sectornum = 0;
908 908
909 /* remember where the file's dir entry is located */ 909 /* remember where the file's dir entry is located */
@@ -935,8 +935,8 @@ int fat_create_file(char* name,
935 err = add_dir_entry(dir, &de, file); 935 err = add_dir_entry(dir, &de, file);
936 if (!err) { 936 if (!err) {
937 file->firstcluster = 0; 937 file->firstcluster = 0;
938 file->nextcluster = 0; 938 file->lastcluster = 0;
939 file->nextsector = 0; 939 file->lastsector = 0;
940 file->sectornum = 0; 940 file->sectornum = 0;
941 } 941 }
942 942
@@ -945,21 +945,38 @@ int fat_create_file(char* name,
945 945
946int fat_closewrite(struct fat_file *file, int size) 946int fat_closewrite(struct fat_file *file, int size)
947{ 947{
948 int endcluster = file->nextcluster; 948 int next, last = file->lastcluster;
949 int next, last = endcluster; 949 int endcluster = last;
950 950
951 /* free unused clusters, if any */ 951 LDEBUGF("fat_closewrite()\n");
952 for ( next = get_next_cluster(last); next; last = next ) { 952
953 LDEBUGF("Clearing cluster %x\n",last); 953 last = get_next_cluster(last);
954 while ( last && last != FAT_EOF_MARK ) {
955 next = get_next_cluster(last);
954 update_fat_entry(last,0); 956 update_fat_entry(last,0);
957 last = next;
955 } 958 }
956 959
957 /* mark last used cluster as last in chain */
958 update_fat_entry(endcluster, FAT_EOF_MARK); 960 update_fat_entry(endcluster, FAT_EOF_MARK);
959 961 update_dir_entry(file, size);
960 flush_fat(); 962 flush_fat();
961 963
962 update_dir_entry(file, size); 964 return 0;
965}
966
967int fat_remove(struct fat_file* file)
968{
969 int next, last = file->firstcluster;
970
971 LDEBUGF("fat_remove(%x)\n",last);
972
973 while ( last != FAT_EOF_MARK ) {
974 LDEBUGF("Freeing cluster %x\n",last);
975 next = get_next_cluster(last);
976 update_fat_entry(last,0);
977 last = next;
978 }
979 update_dir_entry(file, -1);
963 980
964 return 0; 981 return 0;
965} 982}
@@ -967,15 +984,15 @@ int fat_closewrite(struct fat_file *file, int size)
967int fat_readwrite( struct fat_file *file, int sectorcount, 984int fat_readwrite( struct fat_file *file, int sectorcount,
968 void* buf, bool write ) 985 void* buf, bool write )
969{ 986{
970 int cluster = file->nextcluster; 987 int cluster = file->lastcluster;
971 int sector = file->nextsector; 988 int sector = file->lastsector;
972 int numsec = file->sectornum; 989 int numsec = file->sectornum;
973 int first, last; 990 int first=0, last=0;
974 int err, i; 991 int err, i;
975 992
976 LDEBUGF( "fat_readwrite(file:%x,count:%d,buf:%x,%s)\n", 993 LDEBUGF( "fat_readwrite(file:%x,count:%d,buf:%x,%s)\n",
977 cluster,sectorcount,buf,write?"write":"read"); 994 cluster,sectorcount,buf,write?"write":"read");
978 995 LDEBUGF( "fat_readwrite: c=%x s=%x n=%d\n", cluster,sector,numsec);
979 if ( sector == -1 ) 996 if ( sector == -1 )
980 return 0; 997 return 0;
981 998
@@ -995,12 +1012,8 @@ int fat_readwrite( struct fat_file *file, int sectorcount,
995 return -1; 1012 return -1;
996 } 1013 }
997 1014
998 first = sector;
999 last = sector;
1000
1001 /* find sequential sectors and read/write them all at once */ 1015 /* find sequential sectors and read/write them all at once */
1002 for (i=0; i<sectorcount && sector>=0; i++ ) { 1016 for (i=0; i<sectorcount && sector>=0; i++ ) {
1003 numsec++;
1004 if ( numsec >= fat_bpb.bpb_secperclus ) { 1017 if ( numsec >= fat_bpb.bpb_secperclus ) {
1005 int oldcluster = cluster; 1018 int oldcluster = cluster;
1006 cluster = get_next_cluster(cluster); 1019 cluster = get_next_cluster(cluster);
@@ -1008,9 +1021,9 @@ int fat_readwrite( struct fat_file *file, int sectorcount,
1008 if ( write ) { 1021 if ( write ) {
1009 /* writing past end-of-file, 1022 /* writing past end-of-file,
1010 find a new free cluster to use. */ 1023 find a new free cluster to use. */
1011 cluster = find_free_cluster(cluster); 1024 cluster = find_free_cluster(oldcluster+1);
1012 if (!cluster) { 1025 if (!cluster) {
1013 /* no cluster found after last, 1026 /* no free cluster found after last,
1014 search from beginning */ 1027 search from beginning */
1015 cluster = find_free_cluster(0); 1028 cluster = find_free_cluster(0);
1016 if (!cluster) { 1029 if (!cluster) {
@@ -1030,6 +1043,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount,
1030 1043
1031 if (cluster) { 1044 if (cluster) {
1032 sector = cluster2sec(cluster); 1045 sector = cluster2sec(cluster);
1046 LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector);
1033 if (sector<0) 1047 if (sector<0)
1034 return -1; 1048 return -1;
1035 numsec=0; 1049 numsec=0;
@@ -1037,7 +1051,13 @@ int fat_readwrite( struct fat_file *file, int sectorcount,
1037 } 1051 }
1038 else 1052 else
1039 sector++; 1053 sector++;
1054 numsec++;
1040 1055
1056 if (!first)
1057 first = sector;
1058 if (!last)
1059 last = sector;
1060
1041 if ( (sector != last+1) || /* not sequential any more? */ 1061 if ( (sector != last+1) || /* not sequential any more? */
1042 (i == sectorcount-1) || /* last sector requested? */ 1062 (i == sectorcount-1) || /* last sector requested? */
1043 (last-first+1 == 256) ) { /* max 256 sectors per ata request */ 1063 (last-first+1 == 256) ) { /* max 256 sectors per ata request */
@@ -1056,8 +1076,9 @@ int fat_readwrite( struct fat_file *file, int sectorcount,
1056 } 1076 }
1057 last = sector; 1077 last = sector;
1058 } 1078 }
1059 file->nextcluster = cluster; 1079
1060 file->nextsector = sector; 1080 file->lastcluster = cluster;
1081 file->lastsector = sector;
1061 file->sectornum = numsec; 1082 file->sectornum = numsec;
1062 1083
1063 return sectorcount; 1084 return sectorcount;
@@ -1099,8 +1120,8 @@ int fat_seek(struct fat_file *file, int seeksector )
1099 } 1120 }
1100 } 1121 }
1101 1122
1102 file->nextcluster = cluster; 1123 file->lastcluster = cluster;
1103 file->nextsector = sector; 1124 file->lastsector = sector;
1104 file->sectornum = numsec; 1125 file->sectornum = numsec;
1105 return 0; 1126 return 0;
1106} 1127}