diff options
author | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-09-23 21:43:43 +0000 |
---|---|---|
committer | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-09-23 21:43:43 +0000 |
commit | 7f7afe434bfdd46aba66a3bccb4ff1497f26fb0c (patch) | |
tree | eb56a73f65fc60fe613ddc93b4c49b5a96651b9a /firmware/drivers/fat.c | |
parent | 72408f45535c7221c3ef7352fbe14ba5c705baf3 (diff) |
FAT16 support for the Ondio
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5114 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r-- | firmware/drivers/fat.c | 448 |
1 files changed, 344 insertions, 104 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index e41bbaca41..d9aecd8cb0 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c @@ -104,6 +104,7 @@ #define FATLONG_CHKSUM 13 #define CLUSTERS_PER_FAT_SECTOR (SECTOR_SIZE / 4) +#define CLUSTERS_PER_FAT16_SECTOR (SECTOR_SIZE / 2) #define DIR_ENTRIES_PER_SECTOR (SECTOR_SIZE / DIR_ENTRY_SIZE) #define DIR_ENTRY_SIZE 32 #define NAME_BYTES_PER_ENTRY 13 @@ -228,6 +229,11 @@ struct bpb unsigned int startsector; unsigned int dataclusters; struct fsinfo fsinfo; +#ifdef HAVE_FAT16SUPPORT + /* internals for FAT16 support */ + bool is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */ + unsigned int rootdirsectors; /* fixed # of sectors occupied by root dir */ +#endif /* #ifdef HAVE_FAT16SUPPORT */ }; static struct bpb fat_bpb; @@ -281,7 +287,13 @@ static int cluster2sec(int cluster) static int first_sector_of_cluster(int cluster) { - return (cluster - 2) * fat_bpb.bpb_secperclus + fat_bpb.firstdatasector; +#ifdef HAVE_FAT16SUPPORT + /* negative clusters (FAT16 root dir) don't get the 2 offset */ + int zerocluster = cluster < 0 ? 0 : 2; +#else + const int zerocluster = 2; +#endif + return (cluster - zerocluster) * fat_bpb.bpb_secperclus + fat_bpb.firstdatasector; } int fat_startsector(void) @@ -329,6 +341,7 @@ int fat_mount(int startsector) fat_bpb.bpb_secperclus = buf[BPB_SECPERCLUS]; fat_bpb.bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT); fat_bpb.bpb_numfats = buf[BPB_NUMFATS]; + fat_bpb.bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT); /* needed only for FAT16 */ fat_bpb.bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); fat_bpb.bpb_media = buf[BPB_MEDIA]; fat_bpb.bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); @@ -349,8 +362,17 @@ int fat_mount(int startsector) fat_bpb.totalsectors = fat_bpb.bpb_totsec16; else fat_bpb.totalsectors = fat_bpb.bpb_totsec32; - fat_bpb.firstdatasector = fat_bpb.bpb_rsvdseccnt + - fat_bpb.bpb_numfats * fat_bpb.fatsize; + +#ifdef HAVE_FAT16SUPPORT + fat_bpb.rootdirsectors = ((fat_bpb.bpb_rootentcnt * 32) + + (fat_bpb.bpb_bytspersec - 1)) / fat_bpb.bpb_bytspersec; +#endif /* #ifdef HAVE_FAT16SUPPORT */ + + fat_bpb.firstdatasector = fat_bpb.bpb_rsvdseccnt +#ifdef HAVE_FAT16SUPPORT + + fat_bpb.rootdirsectors +#endif + + fat_bpb.bpb_numfats * fat_bpb.fatsize; /* Determine FAT type */ datasec = fat_bpb.totalsectors - fat_bpb.firstdatasector; @@ -365,24 +387,60 @@ int fat_mount(int startsector) #else if ( fat_bpb.dataclusters < 65525 ) #endif - { + { /* FAT16 */ +#ifdef HAVE_FAT16SUPPORT + fat_bpb.is_fat16 = true; + if (fat_bpb.dataclusters < 4085) + { /* FAT12 */ + DEBUGF("This is FAT12. Go away!\n"); + return -2; + } +#else /* #ifdef HAVE_FAT16SUPPORT */ DEBUGF("This is not FAT32. Go away!\n"); return -2; +#endif /* #ifndef HAVE_FAT16SUPPORT */ } - fat_bpb.bpb_extflags = BYTES2INT16(buf,BPB_EXTFLAGS); - fat_bpb.bpb_fsver = BYTES2INT16(buf,BPB_FSVER); - fat_bpb.bpb_rootclus = BYTES2INT32(buf,BPB_ROOTCLUS); - fat_bpb.bpb_fsinfo = BYTES2INT16(buf,BPB_FSINFO); - fat_bpb.bpb_bkbootsec = BYTES2INT16(buf,BPB_BKBOOTSEC); - fat_bpb.bs_drvnum = buf[BS_32_DRVNUM]; - fat_bpb.bs_bootsig = buf[BS_32_BOOTSIG]; +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + { /* FAT16 specific part of BPB */ + int dirclusters; + fat_bpb.bs_drvnum = buf[BS_DRVNUM]; + fat_bpb.bs_bootsig = buf[BS_BOOTSIG]; - if(fat_bpb.bs_bootsig == 0x29) - { - fat_bpb.bs_volid = BYTES2INT32(buf,BS_32_VOLID); - strncpy(fat_bpb.bs_vollab, &buf[BS_32_VOLLAB], 11); - strncpy(fat_bpb.bs_filsystype, &buf[BS_32_FILSYSTYPE], 8); + if(fat_bpb.bs_bootsig == 0x29) + { + fat_bpb.bs_volid = BYTES2INT32(buf, BS_VOLID); + strncpy(fat_bpb.bs_vollab, &buf[BS_VOLLAB], 11); + strncpy(fat_bpb.bs_filsystype, &buf[BS_FILSYSTYPE], 8); + } + fat_bpb.rootdirsector = fat_bpb.bpb_rsvdseccnt + + fat_bpb.bpb_numfats * fat_bpb.bpb_fatsz16; + dirclusters = ((fat_bpb.rootdirsectors + fat_bpb.bpb_secperclus - 1) + / fat_bpb.bpb_secperclus); /* rounded up, to full clusters */ + /* I assign negative pseudo cluster numbers for the root directory, + their range is counted upward until -1. */ + fat_bpb.bpb_rootclus = 0 - dirclusters; /* backwards, before the data */ + } + else +#endif /* #ifdef HAVE_FAT16SUPPORT */ + { /* FAT32 specific part of BPB */ + fat_bpb.bpb_extflags = BYTES2INT16(buf,BPB_EXTFLAGS); + fat_bpb.bpb_fsver = BYTES2INT16(buf,BPB_FSVER); + fat_bpb.bpb_rootclus = BYTES2INT32(buf,BPB_ROOTCLUS); + fat_bpb.bpb_fsinfo = BYTES2INT16(buf,BPB_FSINFO); + fat_bpb.bpb_bkbootsec = BYTES2INT16(buf,BPB_BKBOOTSEC); + fat_bpb.bs_drvnum = buf[BS_32_DRVNUM]; + fat_bpb.bs_bootsig = buf[BS_32_BOOTSIG]; + + if(fat_bpb.bs_bootsig == 0x29) + { + fat_bpb.bs_volid = BYTES2INT32(buf,BS_32_VOLID); + strncpy(fat_bpb.bs_vollab, &buf[BS_32_VOLLAB], 11); + strncpy(fat_bpb.bs_filsystype, &buf[BS_32_FILSYSTYPE], 8); + } + + fat_bpb.rootdirsector = cluster2sec(fat_bpb.bpb_rootclus); } rc = bpb_is_sane(); @@ -392,17 +450,25 @@ int fat_mount(int startsector) return rc * 10 - 3; } - fat_bpb.rootdirsector = cluster2sec(fat_bpb.bpb_rootclus); - - /* Read the fsinfo sector */ - rc = ata_read_sectors(startsector + fat_bpb.bpb_fsinfo, 1, buf); - if (rc < 0) +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) { - DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc); - return rc * 10 - 4; + fat_bpb.fsinfo.freecount = 0xffffffff; /* force recalc below */ + fat_bpb.fsinfo.nextfree = 0xffffffff; + } + else +#endif /* #ifdef HAVE_FAT16SUPPORT */ + { + /* Read the fsinfo sector */ + rc = ata_read_sectors(startsector + fat_bpb.bpb_fsinfo, 1, buf); + if (rc < 0) + { + DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc); + return rc * 10 - 4; + } + fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); + fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); } - fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); - fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); /* calculate freecount if unset */ if ( fat_bpb.fsinfo.freecount == 0xffffffff ) @@ -423,18 +489,41 @@ void fat_recalc_free(void) { int free = 0; unsigned i; - for (i = 0; i<fat_bpb.fatsize; i++) { - unsigned int j; - unsigned int* fat = cache_fat_sector(i); - for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { - unsigned int c = i * CLUSTERS_PER_FAT_SECTOR + j; - if ( c > fat_bpb.dataclusters+1 ) /* nr 0 is unused */ - break; +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + { + for (i = 0; i<fat_bpb.fatsize; i++) { + unsigned int j; + unsigned short* fat = cache_fat_sector(i); + for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) { + unsigned int c = i * CLUSTERS_PER_FAT16_SECTOR + j; + if ( c > fat_bpb.dataclusters+1 ) /* nr 0 is unused */ + break; - if (!(SWAB32(fat[j]) & 0x0fffffff)) { - free++; - if ( fat_bpb.fsinfo.nextfree == 0xffffffff ) - fat_bpb.fsinfo.nextfree = c; + if (SWAB16(fat[j]) == 0x0000) { + free++; + if ( fat_bpb.fsinfo.nextfree == 0xffffffff ) + fat_bpb.fsinfo.nextfree = c; + } + } + } + } + else +#endif /* #ifdef HAVE_FAT16SUPPORT */ + { + for (i = 0; i<fat_bpb.fatsize; i++) { + unsigned int j; + unsigned int* fat = cache_fat_sector(i); + for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { + unsigned int c = i * CLUSTERS_PER_FAT_SECTOR + j; + if ( c > fat_bpb.dataclusters+1 ) /* nr 0 is unused */ + break; + + if (!(SWAB32(fat[j]) & 0x0fffffff)) { + free++; + if ( fat_bpb.fsinfo.nextfree == 0xffffffff ) + fat_bpb.fsinfo.nextfree = c; + } } } } @@ -551,99 +640,203 @@ static unsigned int find_free_cluster(unsigned int startcluster) unsigned int offset; unsigned int i; - sector = startcluster / CLUSTERS_PER_FAT_SECTOR; - offset = startcluster % CLUSTERS_PER_FAT_SECTOR; +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + { + sector = startcluster / CLUSTERS_PER_FAT16_SECTOR; + offset = startcluster % CLUSTERS_PER_FAT16_SECTOR; - for (i = 0; i<fat_bpb.fatsize; i++) { - unsigned int j; - unsigned int nr = (i + sector) % fat_bpb.fatsize; - unsigned int* fat = cache_fat_sector(nr); - if ( !fat ) - break; - for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { - int k = (j + offset) % CLUSTERS_PER_FAT_SECTOR; - if (!(SWAB32(fat[k]) & 0x0fffffff)) { - unsigned int c = nr * CLUSTERS_PER_FAT_SECTOR + k; - /* Ignore the reserved clusters 0 & 1, and also - cluster numbers out of bounds */ - if ( c < 2 || c > fat_bpb.dataclusters+1 ) - continue; - LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); - fat_bpb.fsinfo.nextfree = c; - return c; + for (i = 0; i<fat_bpb.fatsize; i++) { + unsigned int j; + unsigned int nr = (i + sector) % fat_bpb.fatsize; + unsigned short* fat = cache_fat_sector(nr); + if ( !fat ) + break; + for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) { + int k = (j + offset) % CLUSTERS_PER_FAT16_SECTOR; + if (SWAB16(fat[k]) == 0x0000) { + unsigned int c = nr * CLUSTERS_PER_FAT16_SECTOR + k; + /* Ignore the reserved clusters 0 & 1, and also + cluster numbers out of bounds */ + if ( c < 2 || c > fat_bpb.dataclusters+1 ) + continue; + LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); + fat_bpb.fsinfo.nextfree = c; + return c; + } } + offset = 0; } - offset = 0; } + else +#endif /* #ifdef HAVE_FAT16SUPPORT */ + { + sector = startcluster / CLUSTERS_PER_FAT_SECTOR; + offset = startcluster % CLUSTERS_PER_FAT_SECTOR; + + for (i = 0; i<fat_bpb.fatsize; i++) { + unsigned int j; + unsigned int nr = (i + sector) % fat_bpb.fatsize; + unsigned int* fat = cache_fat_sector(nr); + if ( !fat ) + break; + for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { + int k = (j + offset) % CLUSTERS_PER_FAT_SECTOR; + if (!(SWAB32(fat[k]) & 0x0fffffff)) { + unsigned int c = nr * CLUSTERS_PER_FAT_SECTOR + k; + /* Ignore the reserved clusters 0 & 1, and also + cluster numbers out of bounds */ + if ( c < 2 || c > fat_bpb.dataclusters+1 ) + continue; + LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); + fat_bpb.fsinfo.nextfree = c; + return c; + } + } + offset = 0; + } + } + LDEBUGF("find_free_cluster(%x) == 0\n",startcluster); return 0; /* 0 is an illegal cluster number */ } static int update_fat_entry(unsigned int entry, unsigned int val) { - int sector = entry / CLUSTERS_PER_FAT_SECTOR; - int offset = entry % CLUSTERS_PER_FAT_SECTOR; - unsigned int* sec; +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + { + int sector = entry / CLUSTERS_PER_FAT16_SECTOR; + int offset = entry % CLUSTERS_PER_FAT16_SECTOR; + unsigned short* sec; - LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); + val &= 0xFFFF; - if (entry==val) - panicf("Creating FAT loop: %x,%x\n",entry,val); + LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); - if ( entry < 2 ) - panicf("Updating reserved FAT entry %d.\n",entry); + if (entry==val) + panicf("Creating FAT loop: %x,%x\n",entry,val); - sec = cache_fat_sector(sector); - if (!sec) - { - DEBUGF( "update_entry() - Could not cache sector %d\n", sector); - return -1; - } - fat_cache[(sector + fat_bpb.bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; + if ( entry < 2 ) + panicf("Updating reserved FAT entry %d.\n",entry); - if ( val ) { - if (!(SWAB32(sec[offset]) & 0x0fffffff) && - fat_bpb.fsinfo.freecount > 0) - fat_bpb.fsinfo.freecount--; - } - else { - if (SWAB32(sec[offset]) & 0x0fffffff) - fat_bpb.fsinfo.freecount++; + sec = cache_fat_sector(sector); + if (!sec) + { + DEBUGF( "update_entry() - Could not cache sector %d\n", sector); + return -1; + } + fat_cache[(sector + fat_bpb.bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; + + if ( val ) { + if (SWAB16(sec[offset]) == 0x0000 && fat_bpb.fsinfo.freecount > 0) + fat_bpb.fsinfo.freecount--; + } + else { + if (SWAB16(sec[offset])) + fat_bpb.fsinfo.freecount++; + } + + LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb.fsinfo.freecount); + + sec[offset] = SWAB16(val); } + else +#endif /* #ifdef HAVE_FAT16SUPPORT */ + { + int sector = entry / CLUSTERS_PER_FAT_SECTOR; + int offset = entry % CLUSTERS_PER_FAT_SECTOR; + unsigned int* sec; + + LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); - LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb.fsinfo.freecount); + if (entry==val) + panicf("Creating FAT loop: %x,%x\n",entry,val); - /* don't change top 4 bits */ - sec[offset] &= SWAB32(0xf0000000); - sec[offset] |= SWAB32(val & 0x0fffffff); + if ( entry < 2 ) + panicf("Updating reserved FAT entry %d.\n",entry); + + sec = cache_fat_sector(sector); + if (!sec) + { + DEBUGF( "update_entry() - Could not cache sector %d\n", sector); + return -1; + } + fat_cache[(sector + fat_bpb.bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; + + if ( val ) { + if (!(SWAB32(sec[offset]) & 0x0fffffff) && + fat_bpb.fsinfo.freecount > 0) + fat_bpb.fsinfo.freecount--; + } + else { + if (SWAB32(sec[offset]) & 0x0fffffff) + fat_bpb.fsinfo.freecount++; + } + + LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb.fsinfo.freecount); + + /* don't change top 4 bits */ + sec[offset] &= SWAB32(0xf0000000); + sec[offset] |= SWAB32(val & 0x0fffffff); + } return 0; } static int read_fat_entry(unsigned int entry) { - int sector = entry / CLUSTERS_PER_FAT_SECTOR; - int offset = entry % CLUSTERS_PER_FAT_SECTOR; - unsigned int* sec; - - sec = cache_fat_sector(sector); - if (!sec) +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) { - DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); - return -1; + int sector = entry / CLUSTERS_PER_FAT16_SECTOR; + int offset = entry % CLUSTERS_PER_FAT16_SECTOR; + unsigned short* sec; + + sec = cache_fat_sector(sector); + if (!sec) + { + DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); + return -1; + } + + return SWAB16(sec[offset]); } + else +#endif /* #ifdef HAVE_FAT16SUPPORT */ + { + int sector = entry / CLUSTERS_PER_FAT_SECTOR; + int offset = entry % CLUSTERS_PER_FAT_SECTOR; + unsigned int* sec; + + sec = cache_fat_sector(sector); + if (!sec) + { + DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); + return -1; + } - return SWAB32(sec[offset]) & 0x0fffffff; + return SWAB32(sec[offset]) & 0x0fffffff; + } } -static int get_next_cluster(unsigned int cluster) +static int get_next_cluster(int cluster) { int next_cluster; - + int eof_mark = FAT_EOF_MARK; + +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + { + eof_mark &= 0xFFFF; /* only 16 bit */ + if (cluster < 0) /* FAT16 root dir */ + return cluster + 1; /* don't use the FAT */ + } +#endif next_cluster = read_fat_entry(cluster); /* is this last cluster in chain? */ - if ( next_cluster >= FAT_EOF_MARK ) + if ( next_cluster >= eof_mark ) return 0; else return next_cluster; @@ -655,6 +848,11 @@ static int update_fsinfo(void) unsigned int* intptr; int rc; +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + return 0; /* FAT16 has no FsInfo */ +#endif /* #ifdef HAVE_FAT16SUPPORT */ + /* update fsinfo */ rc = ata_read_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo, 1,fsinfo); if (rc < 0) @@ -1311,6 +1509,26 @@ int fat_open(unsigned int startcluster, return 0; } +#ifdef HAVE_FAT16SUPPORT +/* special function to open the FAT16 root dir, + which may not be on cluster boundary */ +int fat_open_root(struct fat_file *file) +{ + int dirclusters; + file->firstcluster = fat_bpb.bpb_rootclus; + file->lastcluster = fat_bpb.bpb_rootclus; + file->lastsector = 0; + file->clusternum = 0; + dirclusters = 0 - fat_bpb.bpb_rootclus; /* bpb_rootclus is the negative */ + file->sectornum = (dirclusters * fat_bpb.bpb_secperclus) + - fat_bpb.rootdirsectors; /* cluster sectors minus real sectors */ + file->eof = false; + + LDEBUGF("fat_open_root(), sector %d\n", cluster2sec(fat_bpb.bpb_rootclus)); + return 0; +} +#endif /* #ifdef HAVE_FAT16SUPPORT */ + int fat_create_file(const char* name, struct fat_file* file, struct fat_dir* dir) @@ -1362,7 +1580,7 @@ int fat_create_dir(const char* name, memset(buf, 0, sizeof buf); sector = cluster2sec(newdir->file.firstcluster); for(i = 0;i < (int)fat_bpb.bpb_secperclus;i++) { - rc = transfer( sector + fat_bpb.startsector + i, 1, buf, true ); + rc = transfer( sector + i, 1, buf, true ); if (rc < 0) return rc * 10 - 2; } @@ -1605,10 +1823,14 @@ static int next_write_cluster(struct fat_file* file, cluster = get_next_cluster(oldcluster); if (!cluster) { - if (oldcluster) + if (oldcluster > 0) cluster = find_free_cluster(oldcluster+1); - else + else if (oldcluster == 0) cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); +#ifdef HAVE_FAT16SUPPORT + else /* negative, pseudo-cluster of the root dir */ + return 0; /* impossible to append something to the root */ +#endif if (cluster) { if (oldcluster) @@ -1639,9 +1861,19 @@ static int transfer( unsigned int start, int count, char* buf, bool write ) { int rc; + start += fat_bpb.startsector; /* offset by partition location */ + LDEBUGF("transfer(s=%x, c=%x, %s)\n",start, count, write?"write":"read"); if (write) { - if (start < fat_bpb.firstdatasector) + unsigned int firstallowed; +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + firstallowed = fat_bpb.rootdirsector; + else +#endif + firstallowed = fat_bpb.firstdatasector; + + if (start < firstallowed + fat_bpb.startsector) panicf("Writing before data\n"); rc = ata_write_sectors(start, count, buf); } @@ -1722,7 +1954,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount, if ( ((sector != first) && (sector != last+1)) || /* not sequential */ (last-first+1 == 256) ) { /* max 256 sectors per ata request */ int count = last - first + 1; - rc = transfer( first + fat_bpb.startsector, count, buf, write ); + rc = transfer( first, count, buf, write ); if (rc < 0) return rc * 10 - 1; @@ -1734,7 +1966,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount, (!eof)) { int count = sector - first + 1; - rc = transfer( first + fat_bpb.startsector, count, buf, write ); + rc = transfer( first, count, buf, write ); if (rc < 0) return rc * 10 - 2; } @@ -1806,8 +2038,19 @@ int fat_opendir(struct fat_dir *dir, unsigned int startcluster, { int rc; + dir->entry = 0; + dir->sector = 0; + if (startcluster == 0) + { +#ifdef HAVE_FAT16SUPPORT + if (fat_bpb.is_fat16) + { /* FAT16 has the root dir outside of the data area */ + return fat_open_root(&dir->file); + } +#endif startcluster = sec2cluster(fat_bpb.rootdirsector); + } rc = fat_open(startcluster, &dir->file, parent_dir); if(rc) @@ -1817,9 +2060,6 @@ int fat_opendir(struct fat_dir *dir, unsigned int startcluster, return rc * 10 - 1; } - dir->entry = 0; - dir->sector = 0; - return 0; } |