add read ahead cache by Rodries

This commit is contained in:
Dave Murphy 2009-05-17 22:16:35 +00:00
parent 527a26f299
commit 206ce78022
12 changed files with 250 additions and 92 deletions

View File

@ -66,7 +66,7 @@ the disc. Otherwise it will try to mount the partition starting at startSector.
cacheSize specifies the number of pages to allocate for the cache. cacheSize specifies the number of pages to allocate for the cache.
This will not startup the disc, so you need to call interface->startup(); first. This will not startup the disc, so you need to call interface->startup(); first.
*/ */
extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage);
/* /*
Unmount the partition specified by name. Unmount the partition specified by name.

View File

@ -82,7 +82,7 @@ the disc. Otherwise it will try to mount the partition starting at startSector.
cacheSize specifies the number of pages to allocate for the cache. cacheSize specifies the number of pages to allocate for the cache.
This will not startup the disc, so you need to call interface->startup(); first. This will not startup the disc, so you need to call interface->startup(); first.
*/ */
extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage);
/* /*
Unmount the partition specified by name. Unmount the partition specified by name.

View File

@ -66,8 +66,7 @@ the disc. Otherwise it will try to mount the partition starting at startSector.
cacheSize specifies the number of pages to allocate for the cache. cacheSize specifies the number of pages to allocate for the cache.
This will not startup the disc, so you need to call interface->startup(); first. This will not startup the disc, so you need to call interface->startup(); first.
*/ */
extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage);
/* /*
Unmount the partition specified by name. Unmount the partition specified by name.
If there are open files, it will attempt to synchronise them to disc. If there are open files, it will attempt to synchronise them to disc.

View File

@ -71,7 +71,7 @@ the disc. Otherwise it will try to mount the partition starting at startSector.
cacheSize specifies the number of pages to allocate for the cache. cacheSize specifies the number of pages to allocate for the cache.
This will not startup the disc, so you need to call interface->startup(); first. This will not startup the disc, so you need to call interface->startup(); first.
*/ */
extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize); extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage);
/* /*
Unmount the partition specified by name. Unmount the partition specified by name.

View File

@ -42,10 +42,11 @@
#include "mem_allocate.h" #include "mem_allocate.h"
#include "bit_ops.h" #include "bit_ops.h"
#include "file_allocation_table.h"
#define CACHE_FREE UINT_MAX #define CACHE_FREE UINT_MAX
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, const DISC_INTERFACE* discInterface) { CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface) {
CACHE* cache; CACHE* cache;
unsigned int i; unsigned int i;
CACHE_ENTRY* cacheEntries; CACHE_ENTRY* cacheEntries;
@ -54,6 +55,10 @@ CACHE* _FAT_cache_constructor (unsigned int numberOfPages, const DISC_INTERFACE*
numberOfPages = 2; numberOfPages = 2;
} }
if (sectorsPerPage < 8) {
sectorsPerPage = 8;
}
cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE)); cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE));
if (cache == NULL) { if (cache == NULL) {
return NULL; return NULL;
@ -61,6 +66,7 @@ CACHE* _FAT_cache_constructor (unsigned int numberOfPages, const DISC_INTERFACE*
cache->disc = discInterface; cache->disc = discInterface;
cache->numberOfPages = numberOfPages; cache->numberOfPages = numberOfPages;
cache->sectorsPerPage = sectorsPerPage;
cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages); cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages);
@ -72,31 +78,33 @@ CACHE* _FAT_cache_constructor (unsigned int numberOfPages, const DISC_INTERFACE*
for (i = 0; i < numberOfPages; i++) { for (i = 0; i < numberOfPages; i++) {
cacheEntries[i].sector = CACHE_FREE; cacheEntries[i].sector = CACHE_FREE;
cacheEntries[i].count = 0; cacheEntries[i].count = 0;
cacheEntries[i].last_access = 0;
cacheEntries[i].dirty = false; cacheEntries[i].dirty = false;
cacheEntries[i].cache = (uint8_t*) _FAT_mem_align ( sectorsPerPage * BYTES_PER_READ );
} }
cache->cacheEntries = cacheEntries; cache->cacheEntries = cacheEntries;
cache->pages = (uint8_t*) _FAT_mem_allocate ( CACHE_PAGE_SIZE * numberOfPages);
if (cache->pages == NULL) {
_FAT_mem_free (cache->cacheEntries);
_FAT_mem_free (cache);
return NULL;
}
return cache; return cache;
} }
void _FAT_cache_destructor (CACHE* cache) { void _FAT_cache_destructor (CACHE* cache) {
unsigned int i;
// Clear out cache before destroying it // Clear out cache before destroying it
_FAT_cache_flush(cache); _FAT_cache_flush(cache);
// Free memory in reverse allocation order // Free memory in reverse allocation order
_FAT_mem_free (cache->pages); for (i = 0; i < cache->numberOfPages; i++) {
_FAT_mem_free (cache->cacheEntries[i].cache);
}
_FAT_mem_free (cache->cacheEntries); _FAT_mem_free (cache->cacheEntries);
_FAT_mem_free (cache); _FAT_mem_free (cache);
}
return; static u32 accessCounter = 0;
static u32 accessTime(){
return accessCounter;
} }
/* /*
@ -104,64 +112,140 @@ Retrieve a sector's page from the cache. If it is not found in the cache,
load it into the cache and return the page it was loaded to. load it into the cache and return the page it was loaded to.
Return CACHE_FREE on error. Return CACHE_FREE on error.
*/ */
static unsigned int _FAT_cache_getSector (CACHE* cache, sec_t sector) { static unsigned int _FAT_cache_getSector (CACHE* cache, sec_t sector, void* buffer) {
unsigned int i; unsigned int i;
CACHE_ENTRY* cacheEntries = cache->cacheEntries; CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages; unsigned int numberOfPages = cache->numberOfPages;
unsigned int sectorsPerPage = cache->sectorsPerPage;
unsigned int leastUsed = 0; unsigned int oldUsed = 0;
unsigned int lowestCount = UINT_MAX; unsigned int oldAccess = cacheEntries[0].last_access;
for (i = 0; (i < numberOfPages) && (cacheEntries[i].sector != sector); i++) { for (i = 0; i < numberOfPages ; i++) {
// While searching for the desired sector, also search for the leased used page if ( sector>=cacheEntries[i].sector && sector < cacheEntries[i].sector+cacheEntries[i].count) {
if ( (cacheEntries[i].sector == CACHE_FREE) || (cacheEntries[i].count < lowestCount) ) { cacheEntries[i].last_access = accessTime();
leastUsed = i; memcpy(buffer, cacheEntries[i].cache + ((sector - cacheEntries[i].sector)*BYTES_PER_READ), BYTES_PER_READ);
lowestCount = cacheEntries[i].count; return true;
}
// While searching for the desired sector, also search for the least recently used page
if ( (cacheEntries[i].sector == CACHE_FREE) || (cacheEntries[i].last_access < oldAccess) ) {
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
} }
} }
// If it found the sector in the cache, return it
if ((i < numberOfPages) && (cacheEntries[i].sector == sector)) {
// Increment usage counter
cacheEntries[i].count += 1;
return i;
}
// If it didn't, replace the least used cache page with the desired sector // If it didn't, replace the least used cache page with the desired sector
if ((cacheEntries[leastUsed].sector != CACHE_FREE) && (cacheEntries[leastUsed].dirty == true)) { if ((cacheEntries[oldUsed].sector != CACHE_FREE) && (cacheEntries[oldUsed].dirty == true)) {
// Write the page back to disc if it has been written to // Write the page back to disc if it has been written to
if (!_FAT_disc_writeSectors (cache->disc, cacheEntries[leastUsed].sector, 1, cache->pages + CACHE_PAGE_SIZE * leastUsed)) { if (!_FAT_disc_writeSectors (cache->disc, cacheEntries[oldUsed].sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache)) {
return CACHE_FREE; return false;
} }
cacheEntries[leastUsed].dirty = false; cacheEntries[oldUsed].dirty = false;
} }
// Load the new sector into the cache // Load the new sector into the cache
if (!_FAT_disc_readSectors (cache->disc, sector, 1, cache->pages + CACHE_PAGE_SIZE * leastUsed)) { if (!_FAT_disc_readSectors (cache->disc, sector, sectorsPerPage, cacheEntries[oldUsed].cache)) {
return CACHE_FREE; return false;
} }
cacheEntries[leastUsed].sector = sector; cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = sectorsPerPage;
// Increment the usage count, don't reset it
// This creates a paging policy of least recently used PAGE, not sector
cacheEntries[oldUsed].last_access = accessTime();
memcpy(buffer, cacheEntries[oldUsed].cache, BYTES_PER_READ);
return true;
}
bool _FAT_cache_getSectors (CACHE* cache, sec_t sector, sec_t numSectors, void* buffer) {
unsigned int i;
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
sec_t sec;
sec_t secs_to_read;
unsigned int oldUsed = 0;
unsigned int oldAccess = cacheEntries[0].last_access;
accessCounter++;
while(numSectors>0)
{
i=0;
while (i < numberOfPages ) {
if ( sector>=cacheEntries[i].sector && sector < cacheEntries[i].sector+cacheEntries[i].count) {
sec=sector-cacheEntries[i].sector;
secs_to_read=cacheEntries[i].count-sec;
if(secs_to_read>numSectors)secs_to_read=numSectors;
memcpy(buffer,cacheEntries[i].cache + (sec*BYTES_PER_READ), secs_to_read*BYTES_PER_READ);
cacheEntries[i].last_access = accessTime();
numSectors=numSectors-secs_to_read;
if(numSectors==0) return true;
buffer+=secs_to_read*BYTES_PER_READ;
sector+=secs_to_read;
i=-1; // recheck all pages again
oldUsed = 0;
oldAccess = cacheEntries[0].last_access;
}
else // While searching for the desired sector, also search for the least recently used page
if ( (cacheEntries[i].sector == CACHE_FREE) || (cacheEntries[i].last_access < oldAccess) ) {
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
}
i++;
}
// If it didn't, replace the least recently used cache page with the desired sector
if ((cacheEntries[oldUsed].sector != CACHE_FREE) && (cacheEntries[oldUsed].dirty == true)) {
// Write the page back to disc if it has been written to
if (!_FAT_disc_writeSectors (cache->disc, cacheEntries[oldUsed].sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache)) {
return false;
}
cacheEntries[oldUsed].dirty = false;
}
cacheEntries[oldUsed].count = cache->sectorsPerPage;
if (!_FAT_disc_readSectors (cache->disc, sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache)) {
return false;
}
cacheEntries[oldUsed].sector = sector;
// Increment the usage count, don't reset it // Increment the usage count, don't reset it
// This creates a paging policy of least used PAGE, not sector // This creates a paging policy of least used PAGE, not sector
cacheEntries[leastUsed].count += 1; cacheEntries[oldUsed].last_access = accessTime();
return leastUsed;
sec=0;
secs_to_read=cacheEntries[oldUsed].count-sec;
if(secs_to_read>numSectors)secs_to_read=numSectors;
memcpy(buffer,cacheEntries[oldUsed].cache + (sec*BYTES_PER_READ), secs_to_read*BYTES_PER_READ);
numSectors=numSectors-secs_to_read;
if(numSectors==0) return true;
buffer+=secs_to_read*BYTES_PER_READ;
sector+=secs_to_read;
oldUsed = 0;
oldAccess = cacheEntries[0].last_access;
}
return false;
} }
/* /*
Reads some data from a cache page, determined by the sector number Reads some data from a cache page, determined by the sector number
*/ */
bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size) { bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size) {
unsigned int page; void* sec;
if (offset + size > BYTES_PER_READ) { if (offset + size > BYTES_PER_READ) {
return false; return false;
} }
sec = (void*) _FAT_mem_align ( BYTES_PER_READ );
page = _FAT_cache_getSector (cache, sector); if(sec == NULL) return false;
if (page == CACHE_FREE) { if(! _FAT_cache_getSector(cache, sector, sec) ) {
_FAT_mem_free(sec);
return false; return false;
} }
memcpy (buffer, cache->pages + (CACHE_PAGE_SIZE * page) + offset, size); memcpy(buffer, sec + offset, size);
_FAT_mem_free(sec);
return true; return true;
} }
@ -182,21 +266,34 @@ bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sect
Writes some data to a cache page, making sure it is loaded into memory first. Writes some data to a cache page, making sure it is loaded into memory first.
*/ */
bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) { bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) {
unsigned int page; unsigned int i;
void* sec;
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
if (offset + size > BYTES_PER_READ) { if (offset + size > BYTES_PER_READ) {
return false; return false;
} }
page = _FAT_cache_getSector (cache, sector); //To be sure sector is in cache
if (page == CACHE_FREE) { sec = (void*) _FAT_mem_align ( BYTES_PER_READ );
if(sec == NULL) return false;
if(! _FAT_cache_getSector(cache, sector, sec) ) {
_FAT_mem_free(sec);
return false; return false;
} }
_FAT_mem_free(sec);
memcpy (cache->pages + (CACHE_PAGE_SIZE * page) + offset, buffer, size); //Find where sector is and write
cache->cacheEntries[page].dirty = true; for (i = 0; i < numberOfPages ; i++) {
if ( sector>=cacheEntries[i].sector && sector < cacheEntries[i].sector+cacheEntries[i].count) {
cacheEntries[i].last_access = accessTime();
memcpy (cacheEntries[i].cache + ((sector-cacheEntries[i].sector)*BYTES_PER_READ) + offset, buffer, size);
cache->cacheEntries[i].dirty = true;
return true; return true;
}
}
return false;
} }
bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) { bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) {
@ -216,39 +313,50 @@ bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_
Writes some data to a cache page, zeroing out the page first Writes some data to a cache page, zeroing out the page first
*/ */
bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) { bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) {
unsigned int page; unsigned int i;
void* sec;
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
if (offset + size > BYTES_PER_READ) { if (offset + size > BYTES_PER_READ) {
return false; return false;
} }
page = _FAT_cache_getSector (cache, sector); //To be sure sector is in cache
if (page == CACHE_FREE) { sec = (void*) _FAT_mem_align ( BYTES_PER_READ );
if(sec == NULL) return false;
if(! _FAT_cache_getSector(cache, sector, sec) ) {
_FAT_mem_free(sec);
return false; return false;
} }
_FAT_mem_free(sec);
memset (cache->pages + (CACHE_PAGE_SIZE * page), 0, CACHE_PAGE_SIZE); //Find where sector is and write
memcpy (cache->pages + (CACHE_PAGE_SIZE * page) + offset, buffer, size); for (i = 0; i < numberOfPages ; i++) {
cache->cacheEntries[page].dirty = true; if ( sector>=cacheEntries[i].sector && sector < cacheEntries[i].sector+cacheEntries[i].count) {
cacheEntries[i].last_access = accessTime();
memset (cacheEntries[i].cache + ((sector-cacheEntries[i].sector)*BYTES_PER_READ), 0, BYTES_PER_READ);
memcpy (cacheEntries[i].cache + ((sector-cacheEntries[i].sector)*BYTES_PER_READ) + offset, buffer, size);
cache->cacheEntries[i].dirty = true;
return true; return true;
}
}
return false;
} }
/* /*
Flushes all dirty pages to disc, clearing the dirty flag. Flushes all dirty pages to disc, clearing the dirty flag.
Also resets all pages' page count to 0.
*/ */
bool _FAT_cache_flush (CACHE* cache) { bool _FAT_cache_flush (CACHE* cache) {
unsigned int i; unsigned int i;
for (i = 0; i < cache->numberOfPages; i++) { for (i = 0; i < cache->numberOfPages; i++) {
if (cache->cacheEntries[i].dirty) { if (cache->cacheEntries[i].dirty) {
if (!_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[i].sector, 1, cache->pages + CACHE_PAGE_SIZE * i)) { if (!_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) {
return false; return false;
} }
} }
cache->cacheEntries[i].count = 0;
cache->cacheEntries[i].dirty = false; cache->cacheEntries[i].dirty = false;
} }
@ -257,10 +365,11 @@ bool _FAT_cache_flush (CACHE* cache) {
void _FAT_cache_invalidate (CACHE* cache) { void _FAT_cache_invalidate (CACHE* cache) {
unsigned int i; unsigned int i;
_FAT_cache_flush(cache);
for (i = 0; i < cache->numberOfPages; i++) { for (i = 0; i < cache->numberOfPages; i++) {
cache->cacheEntries[i].sector = CACHE_FREE; cache->cacheEntries[i].sector = CACHE_FREE;
cache->cacheEntries[i].last_access = 0;
cache->cacheEntries[i].count = 0; cache->cacheEntries[i].count = 0;
cache->cacheEntries[i].dirty = false; cache->cacheEntries[i].dirty = false;
} }
} }

View File

@ -39,22 +39,24 @@
#include "common.h" #include "common.h"
#include "disc.h" #include "disc.h"
#define CACHE_PAGE_SIZE BYTES_PER_READ #define PAGE_SECTORS 64
#define CACHE_PAGE_SIZE (BYTES_PER_READ * PAGE_SECTORS)
typedef struct { typedef struct {
sec_t sector; sec_t sector;
unsigned int count; unsigned int count;
unsigned int last_access;
bool dirty; bool dirty;
uint8_t* cache;
} CACHE_ENTRY; } CACHE_ENTRY;
typedef struct { typedef struct {
const DISC_INTERFACE* disc; const DISC_INTERFACE* disc;
unsigned int numberOfPages; unsigned int numberOfPages;
unsigned int sectorsPerPage;
CACHE_ENTRY* cacheEntries; CACHE_ENTRY* cacheEntries;
uint8_t* pages;
} CACHE; } CACHE;
/* /*
Read data from a sector in the cache Read data from a sector in the cache
If the sector is not in the cache, it will be swapped in If the sector is not in the cache, it will be swapped in
@ -88,6 +90,11 @@ Precondition: offset + size <= BYTES_PER_READ
*/ */
bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size);
/*
Read several sectors from the cache
*/
bool _FAT_cache_getSectors (CACHE* cache, sec_t sector, sec_t numSectors, void* buffer);
/* /*
Read a full sector from the cache Read a full sector from the cache
*/ */
@ -112,7 +119,7 @@ Clear out the contents of the cache without writing any dirty sectors first
*/ */
void _FAT_cache_invalidate (CACHE* cache); void _FAT_cache_invalidate (CACHE* cache);
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, const DISC_INTERFACE* discInterface); CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface);
void _FAT_cache_destructor (CACHE* cache); void _FAT_cache_destructor (CACHE* cache);

View File

@ -57,19 +57,23 @@
// Platform specific options // Platform specific options
#if defined (__wii__) #if defined (__wii__)
#define DEFAULT_CACHE_PAGES 8 #define DEFAULT_CACHE_PAGES 4
#define DEFAULT_SECTORS_PAGE 64
#define USE_LWP_LOCK #define USE_LWP_LOCK
#define USE_RTC_TIME #define USE_RTC_TIME
#elif defined (__gamecube__) #elif defined (__gamecube__)
#define DEFAULT_CACHE_PAGES 8 #define DEFAULT_CACHE_PAGES 4
#define DEFAULT_SECTORS_PAGE 64
#define USE_LWP_LOCK #define USE_LWP_LOCK
#define USE_RTC_TIME #define USE_RTC_TIME
#elif defined (NDS) #elif defined (NDS)
#define DEFAULT_CACHE_PAGES 8 #define DEFAULT_CACHE_PAGES 4
#define DEFAULT_SECTORS_PAGE 8
#define USE_RTC_TIME #define USE_RTC_TIME
#define LIMIT_SECTORS 128 #define LIMIT_SECTORS 128
#elif defined (GBA) #elif defined (GBA)
#define DEFAULT_CACHE_PAGES 2 #define DEFAULT_CACHE_PAGES 2
#define DEFAULT_SECTORS_PAGE 8
#define LIMIT_SECTORS 128 #define LIMIT_SECTORS 128
#endif #endif

View File

@ -36,6 +36,7 @@
#include <errno.h> #include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h>
#include "cache.h" #include "cache.h"
#include "file_allocation_table.h" #include "file_allocation_table.h"
@ -244,6 +245,10 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
_FAT_unlock(&partition->lock); _FAT_unlock(&partition->lock);
/*FILE *fp;
fp=__sfp(r);
fp->_file = (int) file;
setvbuf(fp,NULL,_IONBF,0);*/
return (int) file; return (int) file;
} }
@ -335,6 +340,33 @@ int _FAT_close_r (struct _reent *r, int fd) {
return ret; return ret;
} }
sec_t _FAT_Num_Sectors_To_Cache(CACHE* cache, FILE_POSITION position,PARTITION* partition) {
uint32_t limit;
uint32_t ra_start, ra_end, ra_sectors;
limit = cache->sectorsPerPage;
ra_start = position.cluster;
ra_sectors = - position.sector;
while (true) {
ra_end = ra_start;
ra_start = _FAT_fat_nextCluster(partition, ra_end);
if (ra_start != ra_end + 1)
break;
ra_sectors += partition->sectorsPerCluster;
if (ra_sectors >= limit)
break;
}
if (ra_sectors > limit) ra_sectors = limit;
return ra_sectors;
}
ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) { ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
@ -407,7 +439,7 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
} }
if ((tempVar > 0) && flagNoError) { if ((tempVar > 0) && flagNoError) {
if (! _FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, if (! _FAT_cache_getSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector,
tempVar, ptr)) tempVar, ptr))
{ {
flagNoError = false; flagNoError = false;
@ -450,7 +482,7 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
#endif #endif
(chunkSize + partition->bytesPerCluster <= remain)); (chunkSize + partition->bytesPerCluster <= remain));
if (!_FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster), if (!_FAT_cache_getSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster),
chunkSize / BYTES_PER_READ, ptr)) chunkSize / BYTES_PER_READ, ptr))
{ {
flagNoError = false; flagNoError = false;
@ -476,7 +508,7 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
// Read remaining sectors // Read remaining sectors
tempVar = remain / BYTES_PER_READ; // Number of sectors left tempVar = remain / BYTES_PER_READ; // Number of sectors left
if ((tempVar > 0) && flagNoError) { if ((tempVar > 0) && flagNoError) {
if (!_FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster), if (!_FAT_cache_getSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster),
tempVar, ptr)) tempVar, ptr))
{ {
flagNoError = false; flagNoError = false;

View File

@ -64,8 +64,7 @@ static const devoptab_t dotab_fat = {
NULL /* Device data */ NULL /* Device data */
}; };
bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) {
bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize) {
PARTITION* partition; PARTITION* partition;
devoptab_t* devops; devoptab_t* devops;
char* nameCopy; char* nameCopy;
@ -78,7 +77,7 @@ bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSec
nameCopy = (char*)(devops+1); nameCopy = (char*)(devops+1);
// Initialize the file system // Initialize the file system
partition = _FAT_partition_constructor (interface, cacheSize, startSector); partition = _FAT_partition_constructor (interface, cacheSize, SectorsPerPage, startSector);
if (!partition) { if (!partition) {
_FAT_mem_free (devops); _FAT_mem_free (devops);
return false; return false;
@ -96,7 +95,7 @@ bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSec
} }
bool fatMountSimple (const char* name, const DISC_INTERFACE* interface) { bool fatMountSimple (const char* name, const DISC_INTERFACE* interface) {
return fatMount (name, interface, 0, DEFAULT_CACHE_PAGES); return fatMount (name, interface, 0, DEFAULT_CACHE_PAGES, DEFAULT_SECTORS_PAGE);
} }
void fatUnmount (const char* name) { void fatUnmount (const char* name) {
@ -132,7 +131,7 @@ bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) {
i++) i++)
{ {
disc = _FAT_disc_interfaces[i].getInterface(); disc = _FAT_disc_interfaces[i].getInterface();
if (disc->startup() && fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize)) { if (disc->startup() && fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE)) {
// The first device to successfully mount is set as the default // The first device to successfully mount is set as the default
if (defaultDevice < 0) { if (defaultDevice < 0) {
defaultDevice = i; defaultDevice = i;

View File

@ -37,6 +37,14 @@ static inline void* _FAT_mem_allocate (size_t size) {
return malloc (size); return malloc (size);
} }
static inline void* _FAT_mem_align (size_t size) {
#ifdef __wii__
return memalign (32, size);
#else
return malloc (size);
#endif
}
static inline void _FAT_mem_free (void* mem) { static inline void _FAT_mem_free (void* mem) {
free (mem); free (mem);
} }

View File

@ -97,7 +97,7 @@ enum BPB {
static const char FAT_SIG[3] = {'F', 'A', 'T'}; static const char FAT_SIG[3] = {'F', 'A', 'T'};
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, sec_t startSector) { PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) {
PARTITION* partition; PARTITION* partition;
int i; int i;
uint8_t sectorBuffer[BYTES_PER_READ] = {0}; uint8_t sectorBuffer[BYTES_PER_READ] = {0};
@ -220,7 +220,7 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
} }
// Create a cache to use // Create a cache to use
partition->cache = _FAT_cache_constructor (cacheSize, partition->disc); partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc);
// Set current directory to the root // Set current directory to the root
partition->cwdCluster = partition->rootDirCluster; partition->cwdCluster = partition->rootDirCluster;

View File

@ -72,7 +72,7 @@ typedef struct {
/* /*
Mount the supplied device and return a pointer to the struct necessary to use it Mount the supplied device and return a pointer to the struct necessary to use it
*/ */
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, sec_t startSector); PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector);
/* /*
Dismount the device and free all structures used. Dismount the device and free all structures used.