summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/fat.c80
-rw-r--r--firmware/drivers/fat.h6
2 files changed, 70 insertions, 16 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 3eab47e8b3..dc933be599 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -123,9 +123,14 @@ static unsigned int getcurrdostime(unsigned short *dosdate,
123static int create_dos_name(unsigned char *name, unsigned char *newname); 123static int create_dos_name(unsigned char *name, unsigned char *newname);
124#endif 124#endif
125 125
126/* fat cache */
126static unsigned char *fat_cache[256]; 127static unsigned char *fat_cache[256];
127static int fat_cache_dirty[256]; 128static int fat_cache_dirty[256];
128 129
130/* sectors cache for longname use */
131static unsigned char lastsector[SECTOR_SIZE];
132static unsigned char lastsector2[SECTOR_SIZE];
133
129#ifdef TEST_FAT 134#ifdef TEST_FAT
130 135
131#include "debug.h" 136#include "debug.h"
@@ -788,13 +793,6 @@ int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name)
788 793
789static int parse_direntry(struct fat_direntry *de, unsigned char *buf) 794static int parse_direntry(struct fat_direntry *de, unsigned char *buf)
790{ 795{
791 /* is this a long filename entry? */
792 if ( ( buf[FATDIR_ATTR] & FAT_ATTR_LONG_NAME_MASK ) ==
793 FAT_ATTR_LONG_NAME )
794 {
795 return 0;
796 }
797
798 memset(de, 0, sizeof(struct fat_direntry)); 796 memset(de, 0, sizeof(struct fat_direntry));
799 de->attr = buf[FATDIR_ATTR]; 797 de->attr = buf[FATDIR_ATTR];
800 de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; 798 de->crttimetenth = buf[FATDIR_CRTTIMETENTH];
@@ -930,26 +928,84 @@ int fat_getnext(struct bpb *bpb,
930 int i; 928 int i;
931 int err; 929 int err;
932 unsigned char firstbyte; 930 unsigned char firstbyte;
931 int longarray[20];
932 int longs=0;
933 int sectoridx=0;
933 934
934 while(!done) 935 while(!done)
935 { 936 {
936 /* Look for a free slot */
937 for(i = ent->entry;i < SECTOR_SIZE/32;i++) 937 for(i = ent->entry;i < SECTOR_SIZE/32;i++)
938 { 938 {
939 firstbyte = ent->cached_buf[i*32]; 939 firstbyte = ent->cached_buf[i*32];
940
940 if(firstbyte == 0xe5) 941 if(firstbyte == 0xe5)
942 /* free entry */
941 continue; 943 continue;
942 944
943 if(firstbyte == 0) 945 if(firstbyte == 0)
944 /* no more entries */ 946 /* last entry */
945 return -1; 947 return -1;
946 948
947 if ( parse_direntry(entry, &ent->cached_buf[i*32]) ) { 949 /* longname entry? */
948 done = 1; 950 if ( ( ent->cached_buf[i*32 + FATDIR_ATTR] &
949 break; 951 FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) {
952 longarray[longs++] = i*32 + sectoridx;
953 }
954 else {
955 if ( parse_direntry(entry, &ent->cached_buf[i*32]) ) {
956
957 /* replace shortname with longname? */
958 if ( longs ) {
959 int j,k,l=0;
960
961 /* iterate backwards through the dir entries */
962 for (j=longs-1; j>=0; j--) {
963 unsigned char* ptr = ent->cached_buf;
964 int index = longarray[j];
965
966 /* current or cached sector? */
967 if ( sectoridx >= SECTOR_SIZE ) {
968 if ( sectoridx >= SECTOR_SIZE*2 ) {
969 if ( index >= SECTOR_SIZE ) {
970 if ( index >= SECTOR_SIZE*2 )
971 ptr = ent->cached_buf;
972 else
973 ptr = lastsector;
974 }
975 else
976 ptr = lastsector2;
977 }
978 else {
979 if ( index < SECTOR_SIZE )
980 ptr = lastsector;
981 }
982
983 index &= SECTOR_SIZE-1;
984 }
985
986 /* piece together the name subcomponents */
987 for (k=0; k<5; k++)
988 entry->name[l++] = ptr[index + k*2 + 1];
989 for (k=0; k<6; k++)
990 entry->name[l++] = ptr[index + k*2 + 14];
991 for (k=0; k<2; k++)
992 entry->name[l++] = ptr[index + k*2 + 28];
993 }
994 entry->name[l]=0;
995 }
996 done = 1;
997 break;
998 }
950 } 999 }
951 } 1000 }
952 1001
1002 /* save this sector, for longname use */
1003 if ( sectoridx )
1004 memcpy( lastsector2, ent->cached_buf, SECTOR_SIZE );
1005 else
1006 memcpy( lastsector, ent->cached_buf, SECTOR_SIZE );
1007 sectoridx += SECTOR_SIZE;
1008
953 /* Next sector? */ 1009 /* Next sector? */
954 if(i < SECTOR_SIZE/32) 1010 if(i < SECTOR_SIZE/32)
955 { 1011 {
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h
index e259255d51..907f7b326f 100644
--- a/firmware/drivers/fat.h
+++ b/firmware/drivers/fat.h
@@ -64,7 +64,7 @@ struct bpb
64 64
65struct fat_direntry 65struct fat_direntry
66{ 66{
67 unsigned char name[12]; /* Name plus \0 */ 67 unsigned char name[256]; /* Name plus \0 */
68 unsigned short attr; /* Attributes */ 68 unsigned short attr; /* Attributes */
69 unsigned char crttimetenth; /* Millisecond creation 69 unsigned char crttimetenth; /* Millisecond creation
70 time stamp (0-199) */ 70 time stamp (0-199) */
@@ -74,8 +74,6 @@ struct fat_direntry
74 unsigned short wrttime; /* Last write time */ 74 unsigned short wrttime; /* Last write time */
75 unsigned short wrtdate; /* Last write date */ 75 unsigned short wrtdate; /* Last write date */
76 unsigned int filesize; /* File size in bytes */ 76 unsigned int filesize; /* File size in bytes */
77 unsigned short fstclusterlo;
78 unsigned short fstclusterhi;
79 int firstcluster; /* fstclusterhi<<16 + fstcluslo */ 77 int firstcluster; /* fstclusterhi<<16 + fstcluslo */
80}; 78};
81 79
@@ -91,7 +89,7 @@ struct fat_dirent
91 int entry; 89 int entry;
92 unsigned int cached_sec; 90 unsigned int cached_sec;
93 unsigned int num_sec; 91 unsigned int num_sec;
94 char cached_buf[SECTOR_SIZE]; 92 unsigned char cached_buf[SECTOR_SIZE];
95}; 93};
96 94
97struct fat_fileent 95struct fat_fileent