summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoît Thébaudeau <benoit.thebaudeau@advansee.com>2012-07-20 15:21:08 +0200
committerWolfgang Denk <wd@denx.de>2012-09-02 17:22:10 +0200
commitcc63b25efb908afa3c1405cd6fce1dd5659f91d7 (patch)
tree4d50ec9af4d5b1cf6f2abdfdf0ca49c0b9989ad6
parentcd1b042c5c035719018cffb751714d30513af0a6 (diff)
downloadu-boot-imx-cc63b25efb908afa3c1405cd6fce1dd5659f91d7.zip
u-boot-imx-cc63b25efb908afa3c1405cd6fce1dd5659f91d7.tar.gz
u-boot-imx-cc63b25efb908afa3c1405cd6fce1dd5659f91d7.tar.bz2
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>
-rw-r--r--fs/fat/fat.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index fbc2d7d..fa977b3 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;