From ea1aef9b82c91f93eb0bacccab7b213c374f18f5 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Mon, 8 Mar 2021 11:29:05 +0000 Subject: Have FAT filesystem respect storage buffer alignment on reads This is just a minor cleanup of Solomon Peachy's code, and using per-filesystem buffers instead of a single static buffer. Tested and working on the FiiO M3K. Change-Id: I3c19e8cc24e2f8aa07668c9d1c6d63364815050a --- firmware/drivers/fat.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'firmware') diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index c0e84a2f61..61bf9051f2 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c @@ -266,6 +266,13 @@ static struct bpb } fat_bpbs[NUM_VOLUMES]; /* mounted partition info */ +#ifdef STORAGE_WANTS_ALIGN +#define FAT_BOUNCE_SECTORS 10 +static uint8_t fat_bounce_buffers[NUM_VOLUMES][SECTOR_SIZE*FAT_BOUNCE_SECTORS] STORAGE_ALIGN_ATTR; +#define FAT_BOUNCE_BUFFER(bpb) \ + (fat_bounce_buffers[IF_MV_VOL((bpb)->volume)]) +#endif + #define IS_FAT_SECTOR(bpb, sector) \ (!((sector) >= (bpb)->fatrgnend || (sector) < (bpb)->fatrgnstart)) @@ -2385,8 +2392,35 @@ static long transfer(struct bpb *fat_bpb, unsigned long start, long count, } else { - rc = storage_read_sectors(IF_MD(fat_bpb->drive,) - start + fat_bpb->startsector, count, buf); + void* xferbuf = buf; +#ifdef STORAGE_WANTS_ALIGN + int remain = count; + int xferred = 0; + int aligned = 1; + if(STORAGE_OVERLAP((uintptr_t)buf)) { + xferbuf = FAT_BOUNCE_BUFFER(fat_bpb); + aligned = 0; + count = MIN(remain, FAT_BOUNCE_SECTORS); + } + + while(remain > 0) { +#endif + rc = storage_read_sectors(IF_MD(fat_bpb->drive,) + start + fat_bpb->startsector, count, xferbuf); +#ifdef STORAGE_WANTS_ALIGN + if(rc < 0) + break; + if(LIKELY(aligned)) + break; + + memcpy(buf, xferbuf, count * SECTOR_SIZE); + buf += count * SECTOR_SIZE; + xferred += count; + start += count; + remain -= count; + count = MIN(remain, FAT_BOUNCE_SECTORS); + } +#endif } if (rc < 0) -- cgit v1.2.3