diff options
author | Benoît Thébaudeau <benoit.thebaudeau@advansee.com> | 2012-07-20 15:21:08 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2012-09-02 17:22:10 +0200 |
commit | cc63b25efb908afa3c1405cd6fce1dd5659f91d7 (patch) | |
tree | 4d50ec9af4d5b1cf6f2abdfdf0ca49c0b9989ad6 /fs | |
parent | cd1b042c5c035719018cffb751714d30513af0a6 (diff) |
FAT: get_cluster: Add buffer bouncing
Add a buffer bouncing mechanism to get_cluster. This can be useful
for misaligned applicative buffers passed through get_contents.
This is required for the following patches in the case of data
aligned differently relatively to buffers and clusters.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Cc: Wolfgang Denk <wd@denx.de>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fat/fat.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index fbc2d7de111..fa977b35cb7 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -273,7 +273,6 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) { __u32 idx = 0; __u32 startsect; - __u32 nr_sect; int ret; if (clustnum > 0) { @@ -285,25 +284,44 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect); - nr_sect = size / mydata->sect_size; - ret = disk_read(startsect, nr_sect, buffer); - if (ret != nr_sect) { - debug("Error reading data (got %d)\n", ret); - return -1; - } - if (size % mydata->sect_size) { + if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) { ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); + printf("FAT: Misaligned buffer address (%p)\n", buffer); + + while (size >= mydata->sect_size) { + ret = disk_read(startsect++, 1, tmpbuf); + if (ret != 1) { + debug("Error reading data (got %d)\n", ret); + return -1; + } + + memcpy(buffer, tmpbuf, mydata->sect_size); + buffer += mydata->sect_size; + size -= mydata->sect_size; + } + } else { idx = size / mydata->sect_size; - ret = disk_read(startsect + idx, 1, tmpbuf); + ret = disk_read(startsect, idx, buffer); + if (ret != idx) { + debug("Error reading data (got %d)\n", ret); + return -1; + } + startsect += idx; + idx *= mydata->sect_size; + buffer += idx; + size -= idx; + } + if (size) { + ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); + + ret = disk_read(startsect, 1, tmpbuf); if (ret != 1) { debug("Error reading data (got %d)\n", ret); return -1; } - buffer += idx * mydata->sect_size; - memcpy(buffer, tmpbuf, size % mydata->sect_size); - return 0; + memcpy(buffer, tmpbuf, size); } return 0; |