diff -Naur rockbox/firmware/common/dircache.c rockbox-dircache/firmware/common/dircache.c --- rockbox/firmware/common/dircache.c 2008-01-21 04:05:45.000000000 -0500 +++ rockbox-dircache/firmware/common/dircache.c 2008-01-25 20:05:49.000000000 -0500 @@ -64,12 +64,31 @@ static char dircache_cur_path[MAX_PATH*2]; static struct event_queue dircache_queue; -static long dircache_stack[(DEFAULT_STACK_SIZE + 0x900)/sizeof(long)]; +static long dircache_stack[(DEFAULT_STACK_SIZE + 0xA00)/sizeof(long)]; static const char dircache_thread_name[] = "dircache"; static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS]; static int fdbind_idx = 0; +#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 + +struct dircache_entry *append_position; + +#endif /* #ifdef HAVE_MULTIVOLUME */ + /* --- Internal cache structure control functions --- */ /** @@ -155,6 +174,10 @@ { case DIRCACHE_STOP: case SYS_USB_CONNECTED: +#ifdef HAVE_HOTSWAP + case SYS_HOTSWAP_EXTRACTED: + case SYS_HOTSWAP_INSERTED: +#endif /* Put the event back into the queue. */ queue_post(&dircache_queue, ev.id, ev.data); return true; @@ -166,7 +189,7 @@ /** * 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 +296,35 @@ * 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) + { + snprintf(ce->d_name, VOL_ENUM_POS + 3, vol_names, volume); + ce->name_len = VOL_ENUM_POS + 3; + 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,7 +572,9 @@ start_tick = current_tick; dircache_initializing = true; appflags = 0; - + entry_count = 0; + +#if !defined(HAVE_MULTIVOLUME) || defined(SIMULATOR) #ifdef SIMULATOR pdir = opendir_uncached("/"); if (pdir == NULL) @@ -546,7 +584,7 @@ return -3; } #else - if ( fat_opendir(IF_MV2(volume,) &dir, 0, NULL) < 0 ) { + if ( fat_opendir(IF_MV2(0,) &dir, 0, NULL) < 0 ) { logf("Failed opening root dir"); dircache_initializing = false; return -3; @@ -558,7 +596,7 @@ dircache_size = sizeof(struct dircache_entry); cpu_boost(true); - if (dircache_travel(pdir, dircache_root) < 0) + if (dircache_travel(IF_MV2(0,) pdir, dircache_root) < 0) { logf("dircache_travel failed"); cpu_boost(false); @@ -567,6 +605,35 @@ return -2; } cpu_boost(false); +#else + memset(dircache_cur_path, 0, sizeof(dircache_cur_path)); + dircache_size = sizeof(struct dircache_entry); + + append_position = dircache_root; + + for (i = NUM_VOLUMES; i >= 0; i--) + { + if (fat_ismounted(i)) + { + if ( fat_opendir(IF_MV2(i,) &dir, 0, NULL) < 0 ) { + logf("Failed opening root dir"); + dircache_initializing = false; + return -3; + } + pdir = &dir; + cpu_boost(true); + if (dircache_travel(IF_MV2(i,) pdir, append_position) < 0) + { + logf("dircache_travel failed"); + cpu_boost(false); + dircache_size = 0; + dircache_initializing = false; + return -2; + } + cpu_boost(false); + } + } +#endif logf("Done, %ld KiB used", dircache_size / 1024); @@ -610,6 +677,12 @@ switch (ev.id) { +#ifdef HAVE_HOTSWAP + case SYS_HOTSWAP_EXTRACTED: + case SYS_HOTSWAP_INSERTED: + if (!dircache_initialized) + break; +#endif case DIRCACHE_BUILD: thread_enabled = true; dircache_do_rebuild(); diff -Naur rockbox/firmware/common/file.c rockbox-dircache/firmware/common/file.c --- rockbox/firmware/common/file.c 2007-12-24 04:00:34.000000000 -0500 +++ rockbox-dircache/firmware/common/file.c 2008-01-25 20:02:05.000000000 -0500 @@ -25,13 +25,57 @@ #include "debug.h" #include "dircache.h" #include "system.h" +#include "atoi.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 +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 volume = 0; + const char *temp = name; + + while (*temp == '/') /* skip all leading slashes */ + ++temp; + + if (*temp && !strncmp(temp, vol_names, VOL_ENUM_POS)) + { + temp += VOL_ENUM_POS; /* behind special name */ + volume = atoi(temp); /* number is following */ + temp = strchr(temp, '/'); /* search for slash behind */ + if (temp != NULL) + name = temp; /* use the part behind the volume */ + else + name = "/"; /* else this must be the root dir */ + } + + strncpy(namecopy, name, MAX_PATH); + namecopy[MAX_PATH-1] = '\0'; + + return volume; +} +#endif /* #ifdef HAVE_MULTIVOLUME */ /* These functions provide a roughly POSIX-compatible file IO API. Since the fat32 driver only manages sectors, we maintain a one-sector cache for each open file. This way we can provide byte access without - having to re-read the sector each time. + having to re-read the sector each time. The penalty is the RAM used for the cache and slightly more complex code. */ @@ -114,7 +158,9 @@ return -7; } - fat_open(IF_MV2(unsupported at the moment,) + int volume = strip_volume(pathname, pathnamecopy); + + fat_open(IF_MV2(volume,) ce->startcluster, &(file->fatfile), NULL); diff -Naur rockbox/firmware/export/config.h rockbox-dircache/firmware/export/config.h --- rockbox/firmware/export/config.h 2008-01-21 04:05:44.000000000 -0500 +++ rockbox-dircache/firmware/export/config.h 2008-01-25 20:02:05.000000000 -0500 @@ -304,7 +304,7 @@ /* Enable the directory cache and tagcache in RAM if we have * plenty of RAM. Both features can be enabled independently. */ #if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \ - !defined(BOOTLOADER) && !defined(SANSA_E200) && !defined(SANSA_C200) + !defined(BOOTLOADER) #define HAVE_DIRCACHE #ifdef HAVE_TAGCACHE #define HAVE_TC_RAMCACHE