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 | |
| parent | cd1b042c5c035719018cffb751714d30513af0a6 (diff) | |
| download | olio-uboot-2014.01-cc63b25efb908afa3c1405cd6fce1dd5659f91d7.tar.xz olio-uboot-2014.01-cc63b25efb908afa3c1405cd6fce1dd5659f91d7.zip | |
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.c | 42 | 
1 files changed, 30 insertions, 12 deletions
| diff --git a/fs/fat/fat.c b/fs/fat/fat.c index fbc2d7de1..fa977b35c 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; |