From 52d827a26dec8bc4967cf3c2984a10ace114fa21 Mon Sep 17 00:00:00 2001 From: Miika Pekkarinen Date: Tue, 11 Mar 2008 19:39:26 +0000 Subject: FS#7598 - Dircache support for multivolume targets (by Phil Light). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16632 a1c6a512-1295-4272-9138-f99709370657 --- firmware/common/dir_uncached.c | 20 ++------ firmware/common/dircache.c | 106 +++++++++++++++++++++++++++++----------- firmware/export/config.h | 2 - firmware/include/dir.h | 17 +++++++ firmware/include/dir_uncached.h | 4 ++ 5 files changed, 101 insertions(+), 48 deletions(-) (limited to 'firmware') diff --git a/firmware/common/dir_uncached.c b/firmware/common/dir_uncached.c index e6b59c30ec..129ef35603 100644 --- a/firmware/common/dir_uncached.c +++ b/firmware/common/dir_uncached.c @@ -24,7 +24,6 @@ #include "dir.h" #include "debug.h" #include "atoi.h" -//#include "dircache.h" #define MAX_OPEN_DIRS 8 @@ -32,22 +31,9 @@ static DIR_UNCACHED opendirs[MAX_OPEN_DIRS]; #ifdef HAVE_MULTIVOLUME -/* how to name volumes, first char must be outside of legal file names, - a number gets appended to enumerate, if applicable */ -#ifdef HAVE_MMC -static const char* vol_names = ""; -#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */ -#elif defined(HAVE_HOTSWAP) -static const char* vol_names = ""; -#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */ -#else -static const char* vol_names = ""; -#define VOL_ENUM_POS 3 -#endif - /* returns on which volume this is, and copies the reduced name (sortof a preprocessor for volume-decorated pathnames) */ -static int strip_volume(const char* name, char* namecopy) +int strip_volume(const char* name, char* namecopy) { int volume = 0; const char *temp = name; @@ -55,7 +41,7 @@ static int strip_volume(const char* name, char* namecopy) while (*temp == '/') /* skip all leading slashes */ ++temp; - if (*temp && !strncmp(temp, vol_names, VOL_ENUM_POS)) + if (*temp && !strncmp(temp, VOL_NAMES, VOL_ENUM_POS)) { temp += VOL_ENUM_POS; /* behind special name */ volume = atoi(temp); /* number is following */ @@ -199,7 +185,7 @@ struct dirent_uncached* readdir_uncached(DIR_UNCACHED* dir) memset(theent, 0, sizeof(*theent)); theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME; snprintf(theent->d_name, sizeof(theent->d_name), - vol_names, dir->volumecounter); + VOL_NAMES, dir->volumecounter); return theent; } } diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index ed392d6186..bf8ff45cff 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -37,6 +37,7 @@ #include "usb.h" #include "file.h" #include "buffer.h" +#include "dir.h" #if CONFIG_RTC #include "time.h" #include "timefuncs.h" @@ -51,6 +52,9 @@ DIR_CACHED opendirs[MAX_OPEN_DIRS]; static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; static struct dircache_entry *dircache_root; +#ifdef HAVE_MULTIVOLUME +static struct dircache_entry *append_position; +#endif static bool dircache_initialized = false; static bool dircache_initializing = false; @@ -155,6 +159,9 @@ static bool check_event_queue(void) { case DIRCACHE_STOP: case SYS_USB_CONNECTED: +#ifdef HAVE_HOTSWAP + case SYS_FS_CHANGED: +#endif /* Put the event back into the queue. */ queue_post(&dircache_queue, ev.id, ev.data); return true; @@ -166,7 +173,7 @@ static bool check_event_queue(void) /** * Internal function to iterate a path. */ -static int dircache_scan(struct travel_data *td) +static int dircache_scan(IF_MV2(int volume,) struct travel_data *td) { #ifdef SIMULATOR while ( ( td->entry = readdir_uncached(td->dir) ) ) @@ -273,22 +280,37 @@ static int dircache_scan(struct travel_data *td) * Recursively scan the hard disk and build the cache. */ #ifdef SIMULATOR -static int dircache_travel(DIR_UNCACHED *dir, struct dircache_entry *ce) +static int dircache_travel(IF_MV2(int volume,) DIR_UNCACHED *dir, struct dircache_entry *ce) #else -static int dircache_travel(struct fat_dir *dir, struct dircache_entry *ce) +static int dircache_travel(IF_MV2(int volume,) struct fat_dir *dir, struct dircache_entry *ce) #endif { int depth = 0; int result; memset(ce, 0, sizeof(struct dircache_entry)); + +#if defined(HAVE_MULTIVOLUME) && !defined(SIMULATOR) + if (volume > 0) + { + ce->d_name = ((char *)dircache_root+dircache_size); + snprintf(ce->d_name, VOL_ENUM_POS + 3, VOL_NAMES, volume); + ce->name_len = VOL_ENUM_POS + 3; + dircache_size += ce->name_len; + ce->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME; + ce->size = 0; + append_position = dircache_gen_next(ce); + ce = dircache_gen_down(ce); + } +#endif + dir_recursion[0].dir = dir; dir_recursion[0].ce = ce; dir_recursion[0].first = ce; do { //logf("=> %s", dircache_cur_path); - result = dircache_scan(&dir_recursion[depth]); + result = dircache_scan(IF_MV2(volume,) &dir_recursion[depth]); switch (result) { case 0: /* Leaving the current directory. */ /* Add the standard . and .. entries. */ @@ -536,37 +558,57 @@ static int dircache_do_rebuild(void) start_tick = current_tick; dircache_initializing = true; appflags = 0; + entry_count = 0; -#ifdef SIMULATOR - pdir = opendir_uncached("/"); - if (pdir == NULL) - { - logf("Failed to open rootdir"); - dircache_initializing = false; - return -3; - } -#else - if ( fat_opendir(IF_MV2(volume,) &dir, 0, NULL) < 0 ) { - logf("Failed opening root dir"); - dircache_initializing = false; - return -3; - } - pdir = &dir; -#endif - memset(dircache_cur_path, 0, sizeof(dircache_cur_path)); dircache_size = sizeof(struct dircache_entry); - cpu_boost(true); - if (dircache_travel(pdir, dircache_root) < 0) +#ifdef HAVE_MULTIVOLUME + append_position = dircache_root; + + for (i = NUM_VOLUMES; i >= 0; i--) { - logf("dircache_travel failed"); - cpu_boost(false); - dircache_size = 0; - dircache_initializing = false; - return -2; + if (fat_ismounted(i)) + { +#endif +#ifdef SIMULATOR + pdir = opendir_uncached("/"); + if (pdir == NULL) + { + logf("Failed to open rootdir"); + dircache_initializing = false; + return -3; + } +#else +#ifdef HAVE_MULTIVOLUME + if ( fat_opendir(IF_MV2(i,) &dir, 0, NULL) < 0 ) { +#else + if ( fat_opendir(IF_MV2(0,) &dir, 0, NULL) < 0 ) { +#endif /* HAVE_MULTIVOLUME */ + logf("Failed opening root dir"); + dircache_initializing = false; + return -3; + } + pdir = &dir; +#endif + cpu_boost(true); +#ifdef HAVE_MULTIVOLUME + if (dircache_travel(IF_MV2(i,) pdir, append_position) < 0) +#else + if (dircache_travel(IF_MV2(0,) pdir, dircache_root) < 0) +#endif /* HAVE_MULTIVOLUME */ + { + logf("dircache_travel failed"); + cpu_boost(false); + dircache_size = 0; + dircache_initializing = false; + return -2; + } + cpu_boost(false); +#ifdef HAVE_MULTIVOLUME + } } - cpu_boost(false); +#endif logf("Done, %ld KiB used", dircache_size / 1024); @@ -610,6 +652,12 @@ static void dircache_thread(void) switch (ev.id) { +#ifdef HAVE_HOTSWAP + case SYS_FS_CHANGED: + if (!dircache_initialized) + break; + dircache_initialized = false; +#endif case DIRCACHE_BUILD: thread_enabled = true; dircache_do_rebuild(); diff --git a/firmware/export/config.h b/firmware/export/config.h index c2033dfe23..e1c0cbc938 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -313,9 +313,7 @@ * plenty of RAM. Both features can be enabled independently. */ #if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \ !defined(BOOTLOADER) -#if !defined(SANSA_E200) && !defined(SANSA_C200) #define HAVE_DIRCACHE -#endif #ifdef HAVE_TAGCACHE #define HAVE_TC_RAMCACHE #endif diff --git a/firmware/include/dir.h b/firmware/include/dir.h index 4327b91682..6433f1d2ba 100644 --- a/firmware/include/dir.h +++ b/firmware/include/dir.h @@ -22,6 +22,23 @@ #include "config.h" +#ifdef HAVE_MULTIVOLUME + +/* how to name volumes, first char must be outside of legal file names, + a number gets appended to enumerate, if applicable */ +#ifdef HAVE_MMC +#define VOL_NAMES "" +#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */ +#elif defined(HAVE_HOTSWAP) +#define VOL_NAMES "" +#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */ +#else +#define VOL_NAMES "" +#define VOL_ENUM_POS 3 +#endif + +#endif + #ifdef HAVE_DIRCACHE # include "dircache.h" # define DIR DIR_CACHED diff --git a/firmware/include/dir_uncached.h b/firmware/include/dir_uncached.h index 575c3b67e4..dd00c2c66b 100644 --- a/firmware/include/dir_uncached.h +++ b/firmware/include/dir_uncached.h @@ -75,6 +75,10 @@ typedef struct { char *get_volume_name(int volume); #endif +#ifdef HAVE_MULTIVOLUME + int strip_volume(const char*, char*); +#endif + #ifndef DIRFUNCTIONS_DEFINED extern DIR_UNCACHED* opendir_uncached(const char* name); -- cgit v1.2.3