forked from Imagelibrary/rtems
* ChangeLog, Makefile.am, README, bsp_specs, configure.ac, mk_libnds.sh, patch.libnds, preinstall.am, block/block.c, clock/clock.c, console/console.c, coproc/coproc.S, coproc/coproc.c, coproc/coproc.ld, dswifi/dswifi_license.txt, dswifi/makefile, dswifi/arm7/makefile, dswifi/arm7/source/wifi_arm7.c, dswifi/arm7/source/wifi_arm7.h, dswifi/arm9/makefile, dswifi/arm9/source/sgIP.c, dswifi/arm9/source/sgIP.h, dswifi/arm9/source/sgIP_ARP.c, dswifi/arm9/source/sgIP_ARP.h, dswifi/arm9/source/sgIP_Config.h, dswifi/arm9/source/sgIP_DHCP.c, dswifi/arm9/source/sgIP_DHCP.h, dswifi/arm9/source/sgIP_DNS.c, dswifi/arm9/source/sgIP_DNS.h, dswifi/arm9/source/sgIP_Hub.c, dswifi/arm9/source/sgIP_Hub.h, dswifi/arm9/source/sgIP_ICMP.c, dswifi/arm9/source/sgIP_ICMP.h, dswifi/arm9/source/sgIP_IP.c, dswifi/arm9/source/sgIP_IP.h, dswifi/arm9/source/sgIP_TCP.c, dswifi/arm9/source/sgIP_TCP.h, dswifi/arm9/source/sgIP_UDP.c, dswifi/arm9/source/sgIP_UDP.h, dswifi/arm9/source/sgIP_memblock.c, dswifi/arm9/source/sgIP_memblock.h, dswifi/arm9/source/sgIP_sockets.c, dswifi/arm9/source/sgIP_sockets.h, dswifi/arm9/source/wifi_arm9.c, dswifi/arm9/source/wifi_arm9.h, dswifi/common/source/dsregs.h, dswifi/common/source/spinlock.h, dswifi/common/source/spinlock.s, dswifi/common/source/wifi_shared.h, dswifi/include/dswifi7.h, dswifi/include/dswifi9.h, dswifi/include/dswifi_version.h, dswifi/include/netdb.h, dswifi/include/sgIP_errno.h, dswifi/include/netinet/in.h, fb/fb.c, fb/fb.h, include/bsp.h, include/my_ipc.h, include/tm27.h, include/types.h, include/sys/iosupport.h, irq/irq.c, irq/irq.h, libfat/gba/include/fat.h, libfat/include/fat.h, libfat/nds/include/fat.h, libfat/source/bit_ops.h, libfat/source/cache.c, libfat/source/cache.h, libfat/source/common.h, libfat/source/directory.c, libfat/source/directory.h, libfat/source/fatdir.c, libfat/source/fatdir.h, libfat/source/fatfile.c, libfat/source/fatfile.h, libfat/source/file_allocation_table.c, libfat/source/file_allocation_table.h, libfat/source/filetime.c, libfat/source/filetime.h, libfat/source/libfat.c, libfat/source/mem_allocate.h, libfat/source/partition.c, libfat/source/partition.h, libfat/source/disc_io/disc.c, libfat/source/disc_io/disc.h, libfat/source/disc_io/disc_io.h, libfat/source/disc_io/io_cf_common.c, libfat/source/disc_io/io_cf_common.h, libfat/source/disc_io/io_dldi.h, libfat/source/disc_io/io_dldi.s, libfat/source/disc_io/io_efa2.c, libfat/source/disc_io/io_efa2.h, libfat/source/disc_io/io_fcsr.c, libfat/source/disc_io/io_fcsr.h, libfat/source/disc_io/io_m3_common.c, libfat/source/disc_io/io_m3_common.h, libfat/source/disc_io/io_m3cf.c, libfat/source/disc_io/io_m3cf.h, libfat/source/disc_io/io_m3sd.c, libfat/source/disc_io/io_m3sd.h, libfat/source/disc_io/io_mpcf.c, libfat/source/disc_io/io_mpcf.h, libfat/source/disc_io/io_njsd.c, libfat/source/disc_io/io_njsd.h, libfat/source/disc_io/io_nmmc.c, libfat/source/disc_io/io_nmmc.h, libfat/source/disc_io/io_sc_common.c, libfat/source/disc_io/io_sc_common.h, libfat/source/disc_io/io_sccf.c, libfat/source/disc_io/io_sccf.h, libfat/source/disc_io/io_scsd.c, libfat/source/disc_io/io_scsd.h, libfat/source/disc_io/io_scsd_s.s, libfat/source/disc_io/io_sd_common.c, libfat/source/disc_io/io_sd_common.h, libnds/Makefile.arm7, libnds/Makefile.arm9, libnds/libnds_license.txt, libnds/basicARM7/source/defaultARM7.c, libnds/include/default_font_bin.h, libnds/include/gbfs.h, libnds/include/nds.h, libnds/include/nds/bios.h, libnds/include/nds/card.h, libnds/include/nds/dma.h, libnds/include/nds/interrupts.h, libnds/include/nds/ipc.h, libnds/include/nds/jtypes.h, libnds/include/nds/memory.h, libnds/include/nds/registers_alt.h, libnds/include/nds/reload.h, libnds/include/nds/system.h, libnds/include/nds/timers.h, libnds/include/nds/arm7/audio.h, libnds/include/nds/arm7/clock.h, libnds/include/nds/arm7/serial.h, libnds/include/nds/arm7/touch.h, libnds/include/nds/arm9/background.h, libnds/include/nds/arm9/boxtest.h, libnds/include/nds/arm9/cache.h, libnds/include/nds/arm9/console.h, libnds/include/nds/arm9/exceptions.h, libnds/include/nds/arm9/image.h, libnds/include/nds/arm9/input.h, libnds/include/nds/arm9/math.h, libnds/include/nds/arm9/ndsmotion.h, libnds/include/nds/arm9/pcx.h, libnds/include/nds/arm9/postest.h, libnds/include/nds/arm9/rumble.h, libnds/include/nds/arm9/sound.h, libnds/include/nds/arm9/sprite.h, libnds/include/nds/arm9/trig_lut.h, libnds/include/nds/arm9/video.h, libnds/include/nds/arm9/videoGL.h, libnds/source/arm7/audio.c, libnds/source/arm7/clock.c, libnds/source/arm7/microphone.c, libnds/source/arm7/spi.c, libnds/source/arm7/touch.c, libnds/source/arm7/userSettings.c, libnds/source/arm9/COS.bin, libnds/source/arm9/COS.s, libnds/source/arm9/SIN.bin, libnds/source/arm9/SIN.s, libnds/source/arm9/TAN.bin, libnds/source/arm9/TAN.s, libnds/source/arm9/boxtest.c, libnds/source/arm9/console.c, libnds/source/arm9/dcache.s, libnds/source/arm9/default_font.bin, libnds/source/arm9/default_font.s, libnds/source/arm9/exceptionHandler.S, libnds/source/arm9/exceptionHandler.s, libnds/source/arm9/exceptions.c, libnds/source/arm9/gurumeditation.c, libnds/source/arm9/icache.s, libnds/source/arm9/image.c, libnds/source/arm9/initSystem.c, libnds/source/arm9/keys.c, libnds/source/arm9/ndsmotion.c, libnds/source/arm9/pcx.c, libnds/source/arm9/rumble.c, libnds/source/arm9/sound.c, libnds/source/arm9/system.c, libnds/source/arm9/touch.c, libnds/source/arm9/video.c, libnds/source/arm9/videoGL.c, libnds/source/common/biosCalls.s, libnds/source/common/card.c, libnds/source/common/gbfs.c, libnds/source/common/interruptDispatcher.s, libnds/source/common/interrupts.c, rtc/rtc.c, sound/sound.c, sound/sound.h, start/start.S, startup/linkcmds, startup/start.c, timer/timer.c, tools/Makefile.am, tools/bin2s, tools/bin2s.c, tools/configure.ac, tools/runtest, tools/ndstool/include/arm7_sha1_homebrew.h, tools/ndstool/include/arm7_sha1_nintendo.h, tools/ndstool/include/banner.h, tools/ndstool/include/bigint.h, tools/ndstool/include/crc.h, tools/ndstool/include/default_icon.h, tools/ndstool/include/encryption.h, tools/ndstool/include/header.h, tools/ndstool/include/hook.h, tools/ndstool/include/little.h, tools/ndstool/include/loadme.h, tools/ndstool/include/logo.h, tools/ndstool/include/ndscreate.h, tools/ndstool/include/ndsextract.h, tools/ndstool/include/ndstool.h, tools/ndstool/include/ndstree.h, tools/ndstool/include/overlay.h, tools/ndstool/include/passme.h, tools/ndstool/include/passme_sram.h, tools/ndstool/include/passme_vhd1.h, tools/ndstool/include/passme_vhd2.h, tools/ndstool/include/raster.h, tools/ndstool/include/sha1.h, tools/ndstool/include/types.h, tools/ndstool/source/arm7_sha1_homebrew.c, tools/ndstool/source/arm7_sha1_nintendo.c, tools/ndstool/source/banner.cpp, tools/ndstool/source/bigint.cpp, tools/ndstool/source/compile_date.c, tools/ndstool/source/crc.cpp, tools/ndstool/source/default_icon.c, tools/ndstool/source/encryption.cpp, tools/ndstool/source/header.cpp, tools/ndstool/source/hook.cpp, tools/ndstool/source/loadme.c, tools/ndstool/source/logo.cpp, tools/ndstool/source/ndscodes.cpp, tools/ndstool/source/ndscreate.cpp, tools/ndstool/source/ndsextract.cpp, tools/ndstool/source/ndstool.cpp, tools/ndstool/source/ndstree.cpp, tools/ndstool/source/passme.cpp, tools/ndstool/source/passme_sram.c, tools/ndstool/source/raster.cpp, tools/ndstool/source/sha1.cpp, touchscreen/README.reco, touchscreen/parser.c, touchscreen/reco.c, touchscreen/reco.h, touchscreen/touchscreen.c, touchscreen/touchscreen.h, wifi/compat.c, wifi/compat.h, wifi/wifi.c: New files.
238 lines
6.9 KiB
C
238 lines
6.9 KiB
C
/*
|
|
cache.c
|
|
The cache is not visible to the user. It should be flushed
|
|
when any file is closed or changes are made to the filesystem.
|
|
|
|
This cache implements a least-used-page replacement policy. This will
|
|
distribute sectors evenly over the pages, so if less than the maximum
|
|
pages are used at once, they should all eventually remain in the cache.
|
|
This also has the benefit of throwing out old sectors, so as not to keep
|
|
too many stale pages around.
|
|
|
|
Copyright (c) 2006 Michael "Chishm" Chisholm
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation and/or
|
|
other materials provided with the distribution.
|
|
3. The name of the author may not be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "common.h"
|
|
#include "cache.h"
|
|
#include "disc_io/disc.h"
|
|
|
|
#include "mem_allocate.h"
|
|
|
|
#define CACHE_FREE 0xFFFFFFFF
|
|
|
|
CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface) {
|
|
CACHE* cache;
|
|
u32 i;
|
|
CACHE_ENTRY* cacheEntries;
|
|
|
|
if (numberOfPages < 2) {
|
|
numberOfPages = 2;
|
|
}
|
|
|
|
cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE));
|
|
if (cache == NULL) {
|
|
return false;
|
|
}
|
|
|
|
cache->disc = discInterface;
|
|
cache->numberOfPages = numberOfPages;
|
|
|
|
|
|
cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages);
|
|
if (cacheEntries == NULL) {
|
|
_FAT_mem_free (cache);
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < numberOfPages; i++) {
|
|
cacheEntries[i].sector = CACHE_FREE;
|
|
cacheEntries[i].count = 0;
|
|
cacheEntries[i].dirty = false;
|
|
}
|
|
|
|
cache->cacheEntries = cacheEntries;
|
|
|
|
cache->pages = (u8*) _FAT_mem_allocate ( CACHE_PAGE_SIZE * numberOfPages);
|
|
if (cache->pages == NULL) {
|
|
_FAT_mem_free (cache->cacheEntries);
|
|
_FAT_mem_free (cache);
|
|
return false;
|
|
}
|
|
|
|
return cache;
|
|
}
|
|
|
|
void _FAT_cache_destructor (CACHE* cache) {
|
|
// Clear out cache before destroying it
|
|
_FAT_cache_flush(cache);
|
|
|
|
// Free memory in reverse allocation order
|
|
_FAT_mem_free (cache->pages);
|
|
_FAT_mem_free (cache->cacheEntries);
|
|
_FAT_mem_free (cache);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
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.
|
|
Return CACHE_FREE on error.
|
|
*/
|
|
static u32 _FAT_cache_getSector (CACHE* cache, u32 sector) {
|
|
u32 i;
|
|
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
|
|
u32 numberOfPages = cache->numberOfPages;
|
|
|
|
u32 leastUsed = 0;
|
|
u32 lowestCount = 0xFFFFFFFF;
|
|
|
|
for (i = 0; (i < numberOfPages) && (cacheEntries[i].sector != sector); i++) {
|
|
// While searching for the desired sector, also search for the leased used page
|
|
if ( (cacheEntries[i].sector == CACHE_FREE) || (cacheEntries[i].count < lowestCount) ) {
|
|
leastUsed = i;
|
|
lowestCount = cacheEntries[i].count;
|
|
}
|
|
}
|
|
|
|
// 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 ((cacheEntries[leastUsed].sector != CACHE_FREE) && (cacheEntries[leastUsed].dirty == true)) {
|
|
// 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)) {
|
|
return CACHE_FREE;
|
|
}
|
|
cacheEntries[leastUsed].dirty = false;
|
|
}
|
|
|
|
// Load the new sector into the cache
|
|
if (!_FAT_disc_readSectors (cache->disc, sector, 1, cache->pages + CACHE_PAGE_SIZE * leastUsed)) {
|
|
return CACHE_FREE;
|
|
}
|
|
cacheEntries[leastUsed].sector = sector;
|
|
// Increment the usage count, don't reset it
|
|
// This creates a paging policy of least used PAGE, not sector
|
|
cacheEntries[leastUsed].count += 1;
|
|
return leastUsed;
|
|
}
|
|
|
|
/*
|
|
Reads some data from a cache page, determined by the sector number
|
|
*/
|
|
bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size) {
|
|
u32 page;
|
|
|
|
if (offset + size > BYTES_PER_READ) {
|
|
return false;
|
|
}
|
|
|
|
page = _FAT_cache_getSector (cache, sector);
|
|
if (page == CACHE_FREE) {
|
|
return false;
|
|
}
|
|
memcpy (buffer, cache->pages + (CACHE_PAGE_SIZE * page) + offset, size);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Writes some data to a cache page, making sure it is loaded into memory first.
|
|
*/
|
|
bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size) {
|
|
u32 page;
|
|
|
|
if (offset + size > BYTES_PER_READ) {
|
|
return false;
|
|
}
|
|
|
|
page = _FAT_cache_getSector (cache, sector);
|
|
if (page == CACHE_FREE) {
|
|
return false;
|
|
}
|
|
|
|
memcpy (cache->pages + (CACHE_PAGE_SIZE * page) + offset, buffer, size);
|
|
cache->cacheEntries[page].dirty = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Writes some data to a cache page, zeroing out the page first
|
|
*/
|
|
bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size) {
|
|
u32 page;
|
|
|
|
if (offset + size > BYTES_PER_READ) {
|
|
return false;
|
|
}
|
|
|
|
page = _FAT_cache_getSector (cache, sector);
|
|
if (page == CACHE_FREE) {
|
|
return false;
|
|
}
|
|
|
|
memset (cache->pages + (CACHE_PAGE_SIZE * page), 0, CACHE_PAGE_SIZE);
|
|
memcpy (cache->pages + (CACHE_PAGE_SIZE * page) + offset, buffer, size);
|
|
cache->cacheEntries[page].dirty = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
Flushes all dirty pages to disc, clearing the dirty flag.
|
|
Also resets all pages' page count to 0.
|
|
*/
|
|
bool _FAT_cache_flush (CACHE* cache) {
|
|
u32 i;
|
|
|
|
for (i = 0; i < cache->numberOfPages; i++) {
|
|
if (cache->cacheEntries[i].dirty) {
|
|
if (!_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[i].sector, 1, cache->pages + CACHE_PAGE_SIZE * i)) {
|
|
return CACHE_FREE;
|
|
}
|
|
}
|
|
cache->cacheEntries[i].count = 0;
|
|
cache->cacheEntries[i].dirty = false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void _FAT_cache_invalidate (CACHE* cache) {
|
|
int i;
|
|
for (i = 0; i < cache->numberOfPages; i++) {
|
|
cache->cacheEntries[i].sector = CACHE_FREE;
|
|
cache->cacheEntries[i].count = 0;
|
|
cache->cacheEntries[i].dirty = false;
|
|
}
|
|
}
|