summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/fat.c38
1 files changed, 36 insertions, 2 deletions
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
266 266
267} fat_bpbs[NUM_VOLUMES]; /* mounted partition info */ 267} fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
268 268
269#ifdef STORAGE_WANTS_ALIGN
270#define FAT_BOUNCE_SECTORS 10
271static uint8_t fat_bounce_buffers[NUM_VOLUMES][SECTOR_SIZE*FAT_BOUNCE_SECTORS] STORAGE_ALIGN_ATTR;
272#define FAT_BOUNCE_BUFFER(bpb) \
273 (fat_bounce_buffers[IF_MV_VOL((bpb)->volume)])
274#endif
275
269#define IS_FAT_SECTOR(bpb, sector) \ 276#define IS_FAT_SECTOR(bpb, sector) \
270 (!((sector) >= (bpb)->fatrgnend || (sector) < (bpb)->fatrgnstart)) 277 (!((sector) >= (bpb)->fatrgnend || (sector) < (bpb)->fatrgnstart))
271 278
@@ -2385,8 +2392,35 @@ static long transfer(struct bpb *fat_bpb, unsigned long start, long count,
2385 } 2392 }
2386 else 2393 else
2387 { 2394 {
2388 rc = storage_read_sectors(IF_MD(fat_bpb->drive,) 2395 void* xferbuf = buf;
2389 start + fat_bpb->startsector, count, buf); 2396#ifdef STORAGE_WANTS_ALIGN
2397 int remain = count;
2398 int xferred = 0;
2399 int aligned = 1;
2400 if(STORAGE_OVERLAP((uintptr_t)buf)) {
2401 xferbuf = FAT_BOUNCE_BUFFER(fat_bpb);
2402 aligned = 0;
2403 count = MIN(remain, FAT_BOUNCE_SECTORS);
2404 }
2405
2406 while(remain > 0) {
2407#endif
2408 rc = storage_read_sectors(IF_MD(fat_bpb->drive,)
2409 start + fat_bpb->startsector, count, xferbuf);
2410#ifdef STORAGE_WANTS_ALIGN
2411 if(rc < 0)
2412 break;
2413 if(LIKELY(aligned))
2414 break;
2415
2416 memcpy(buf, xferbuf, count * SECTOR_SIZE);
2417 buf += count * SECTOR_SIZE;
2418 xferred += count;
2419 start += count;
2420 remain -= count;
2421 count = MIN(remain, FAT_BOUNCE_SECTORS);
2422 }
2423#endif
2390 } 2424 }
2391 2425
2392 if (rc < 0) 2426 if (rc < 0)