summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2008-03-11 19:39:26 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2008-03-11 19:39:26 +0000
commit52d827a26dec8bc4967cf3c2984a10ace114fa21 (patch)
tree83b9660b904934a62df38ee0ed138c66f3cdebb1
parentafde7f74d4325c3a5a6883167c1f74f4fb689f90 (diff)
downloadrockbox-52d827a26dec8bc4967cf3c2984a10ace114fa21.tar.gz
rockbox-52d827a26dec8bc4967cf3c2984a10ace114fa21.zip
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
-rw-r--r--docs/CREDITS2
-rw-r--r--firmware/common/dir_uncached.c20
-rw-r--r--firmware/common/dircache.c106
-rw-r--r--firmware/export/config.h2
-rw-r--r--firmware/include/dir.h17
-rw-r--r--firmware/include/dir_uncached.h4
6 files changed, 102 insertions, 49 deletions
diff --git a/docs/CREDITS b/docs/CREDITS
index c4d78edd85..6bbc868343 100644
--- a/docs/CREDITS
+++ b/docs/CREDITS
@@ -380,7 +380,7 @@ Keith Perri
380Mark Fawcus 380Mark Fawcus
381Ivan Pesic 381Ivan Pesic
382Marcel Barbulescu 382Marcel Barbulescu
383 383Phil Light
384 384
385The libmad team 385The libmad team
386The wavpack team 386The wavpack team
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 @@
24#include "dir.h" 24#include "dir.h"
25#include "debug.h" 25#include "debug.h"
26#include "atoi.h" 26#include "atoi.h"
27//#include "dircache.h"
28 27
29#define MAX_OPEN_DIRS 8 28#define MAX_OPEN_DIRS 8
30 29
@@ -32,22 +31,9 @@ static DIR_UNCACHED opendirs[MAX_OPEN_DIRS];
32 31
33#ifdef HAVE_MULTIVOLUME 32#ifdef HAVE_MULTIVOLUME
34 33
35/* how to name volumes, first char must be outside of legal file names,
36 a number gets appended to enumerate, if applicable */
37#ifdef HAVE_MMC
38static const char* vol_names = "<MMC%d>";
39#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */
40#elif defined(HAVE_HOTSWAP)
41static const char* vol_names = "<microSD%d>";
42#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */
43#else
44static const char* vol_names = "<HD%d>";
45#define VOL_ENUM_POS 3
46#endif
47
48/* returns on which volume this is, and copies the reduced name 34/* returns on which volume this is, and copies the reduced name
49 (sortof a preprocessor for volume-decorated pathnames) */ 35 (sortof a preprocessor for volume-decorated pathnames) */
50static int strip_volume(const char* name, char* namecopy) 36int strip_volume(const char* name, char* namecopy)
51{ 37{
52 int volume = 0; 38 int volume = 0;
53 const char *temp = name; 39 const char *temp = name;
@@ -55,7 +41,7 @@ static int strip_volume(const char* name, char* namecopy)
55 while (*temp == '/') /* skip all leading slashes */ 41 while (*temp == '/') /* skip all leading slashes */
56 ++temp; 42 ++temp;
57 43
58 if (*temp && !strncmp(temp, vol_names, VOL_ENUM_POS)) 44 if (*temp && !strncmp(temp, VOL_NAMES, VOL_ENUM_POS))
59 { 45 {
60 temp += VOL_ENUM_POS; /* behind special name */ 46 temp += VOL_ENUM_POS; /* behind special name */
61 volume = atoi(temp); /* number is following */ 47 volume = atoi(temp); /* number is following */
@@ -199,7 +185,7 @@ struct dirent_uncached* readdir_uncached(DIR_UNCACHED* dir)
199 memset(theent, 0, sizeof(*theent)); 185 memset(theent, 0, sizeof(*theent));
200 theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME; 186 theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
201 snprintf(theent->d_name, sizeof(theent->d_name), 187 snprintf(theent->d_name, sizeof(theent->d_name),
202 vol_names, dir->volumecounter); 188 VOL_NAMES, dir->volumecounter);
203 return theent; 189 return theent;
204 } 190 }
205 } 191 }
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 @@
37#include "usb.h" 37#include "usb.h"
38#include "file.h" 38#include "file.h"
39#include "buffer.h" 39#include "buffer.h"
40#include "dir.h"
40#if CONFIG_RTC 41#if CONFIG_RTC
41#include "time.h" 42#include "time.h"
42#include "timefuncs.h" 43#include "timefuncs.h"
@@ -51,6 +52,9 @@ DIR_CACHED opendirs[MAX_OPEN_DIRS];
51 52
52static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; 53static struct dircache_entry *fd_bindings[MAX_OPEN_FILES];
53static struct dircache_entry *dircache_root; 54static struct dircache_entry *dircache_root;
55#ifdef HAVE_MULTIVOLUME
56static struct dircache_entry *append_position;
57#endif
54 58
55static bool dircache_initialized = false; 59static bool dircache_initialized = false;
56static bool dircache_initializing = false; 60static bool dircache_initializing = false;
@@ -155,6 +159,9 @@ static bool check_event_queue(void)
155 { 159 {
156 case DIRCACHE_STOP: 160 case DIRCACHE_STOP:
157 case SYS_USB_CONNECTED: 161 case SYS_USB_CONNECTED:
162#ifdef HAVE_HOTSWAP
163 case SYS_FS_CHANGED:
164#endif
158 /* Put the event back into the queue. */ 165 /* Put the event back into the queue. */
159 queue_post(&dircache_queue, ev.id, ev.data); 166 queue_post(&dircache_queue, ev.id, ev.data);
160 return true; 167 return true;
@@ -166,7 +173,7 @@ static bool check_event_queue(void)
166/** 173/**
167 * Internal function to iterate a path. 174 * Internal function to iterate a path.
168 */ 175 */
169static int dircache_scan(struct travel_data *td) 176static int dircache_scan(IF_MV2(int volume,) struct travel_data *td)
170{ 177{
171#ifdef SIMULATOR 178#ifdef SIMULATOR
172 while ( ( td->entry = readdir_uncached(td->dir) ) ) 179 while ( ( td->entry = readdir_uncached(td->dir) ) )
@@ -273,22 +280,37 @@ static int dircache_scan(struct travel_data *td)
273 * Recursively scan the hard disk and build the cache. 280 * Recursively scan the hard disk and build the cache.
274 */ 281 */
275#ifdef SIMULATOR 282#ifdef SIMULATOR
276static int dircache_travel(DIR_UNCACHED *dir, struct dircache_entry *ce) 283static int dircache_travel(IF_MV2(int volume,) DIR_UNCACHED *dir, struct dircache_entry *ce)
277#else 284#else
278static int dircache_travel(struct fat_dir *dir, struct dircache_entry *ce) 285static int dircache_travel(IF_MV2(int volume,) struct fat_dir *dir, struct dircache_entry *ce)
279#endif 286#endif
280{ 287{
281 int depth = 0; 288 int depth = 0;
282 int result; 289 int result;
283 290
284 memset(ce, 0, sizeof(struct dircache_entry)); 291 memset(ce, 0, sizeof(struct dircache_entry));
292
293#if defined(HAVE_MULTIVOLUME) && !defined(SIMULATOR)
294 if (volume > 0)
295 {
296 ce->d_name = ((char *)dircache_root+dircache_size);
297 snprintf(ce->d_name, VOL_ENUM_POS + 3, VOL_NAMES, volume);
298 ce->name_len = VOL_ENUM_POS + 3;
299 dircache_size += ce->name_len;
300 ce->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
301 ce->size = 0;
302 append_position = dircache_gen_next(ce);
303 ce = dircache_gen_down(ce);
304 }
305#endif
306
285 dir_recursion[0].dir = dir; 307 dir_recursion[0].dir = dir;
286 dir_recursion[0].ce = ce; 308 dir_recursion[0].ce = ce;
287 dir_recursion[0].first = ce; 309 dir_recursion[0].first = ce;
288 310
289 do { 311 do {
290 //logf("=> %s", dircache_cur_path); 312 //logf("=> %s", dircache_cur_path);
291 result = dircache_scan(&dir_recursion[depth]); 313 result = dircache_scan(IF_MV2(volume,) &dir_recursion[depth]);
292 switch (result) { 314 switch (result) {
293 case 0: /* Leaving the current directory. */ 315 case 0: /* Leaving the current directory. */
294 /* Add the standard . and .. entries. */ 316 /* Add the standard . and .. entries. */
@@ -536,37 +558,57 @@ static int dircache_do_rebuild(void)
536 start_tick = current_tick; 558 start_tick = current_tick;
537 dircache_initializing = true; 559 dircache_initializing = true;
538 appflags = 0; 560 appflags = 0;
561 entry_count = 0;
539 562
540#ifdef SIMULATOR
541 pdir = opendir_uncached("/");
542 if (pdir == NULL)
543 {
544 logf("Failed to open rootdir");
545 dircache_initializing = false;
546 return -3;
547 }
548#else
549 if ( fat_opendir(IF_MV2(volume,) &dir, 0, NULL) < 0 ) {
550 logf("Failed opening root dir");
551 dircache_initializing = false;
552 return -3;
553 }
554 pdir = &dir;
555#endif
556
557 memset(dircache_cur_path, 0, sizeof(dircache_cur_path)); 563 memset(dircache_cur_path, 0, sizeof(dircache_cur_path));
558 dircache_size = sizeof(struct dircache_entry); 564 dircache_size = sizeof(struct dircache_entry);
559 565
560 cpu_boost(true); 566#ifdef HAVE_MULTIVOLUME
561 if (dircache_travel(pdir, dircache_root) < 0) 567 append_position = dircache_root;
568
569 for (i = NUM_VOLUMES; i >= 0; i--)
562 { 570 {
563 logf("dircache_travel failed"); 571 if (fat_ismounted(i))
564 cpu_boost(false); 572 {
565 dircache_size = 0; 573#endif
566 dircache_initializing = false; 574#ifdef SIMULATOR
567 return -2; 575 pdir = opendir_uncached("/");
576 if (pdir == NULL)
577 {
578 logf("Failed to open rootdir");
579 dircache_initializing = false;
580 return -3;
581 }
582#else
583#ifdef HAVE_MULTIVOLUME
584 if ( fat_opendir(IF_MV2(i,) &dir, 0, NULL) < 0 ) {
585#else
586 if ( fat_opendir(IF_MV2(0,) &dir, 0, NULL) < 0 ) {
587#endif /* HAVE_MULTIVOLUME */
588 logf("Failed opening root dir");
589 dircache_initializing = false;
590 return -3;
591 }
592 pdir = &dir;
593#endif
594 cpu_boost(true);
595#ifdef HAVE_MULTIVOLUME
596 if (dircache_travel(IF_MV2(i,) pdir, append_position) < 0)
597#else
598 if (dircache_travel(IF_MV2(0,) pdir, dircache_root) < 0)
599#endif /* HAVE_MULTIVOLUME */
600 {
601 logf("dircache_travel failed");
602 cpu_boost(false);
603 dircache_size = 0;
604 dircache_initializing = false;
605 return -2;
606 }
607 cpu_boost(false);
608#ifdef HAVE_MULTIVOLUME
609 }
568 } 610 }
569 cpu_boost(false); 611#endif
570 612
571 logf("Done, %ld KiB used", dircache_size / 1024); 613 logf("Done, %ld KiB used", dircache_size / 1024);
572 614
@@ -610,6 +652,12 @@ static void dircache_thread(void)
610 652
611 switch (ev.id) 653 switch (ev.id)
612 { 654 {
655#ifdef HAVE_HOTSWAP
656 case SYS_FS_CHANGED:
657 if (!dircache_initialized)
658 break;
659 dircache_initialized = false;
660#endif
613 case DIRCACHE_BUILD: 661 case DIRCACHE_BUILD:
614 thread_enabled = true; 662 thread_enabled = true;
615 dircache_do_rebuild(); 663 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 @@
313 * plenty of RAM. Both features can be enabled independently. */ 313 * plenty of RAM. Both features can be enabled independently. */
314#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \ 314#if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \
315 !defined(BOOTLOADER) 315 !defined(BOOTLOADER)
316#if !defined(SANSA_E200) && !defined(SANSA_C200)
317#define HAVE_DIRCACHE 316#define HAVE_DIRCACHE
318#endif
319#ifdef HAVE_TAGCACHE 317#ifdef HAVE_TAGCACHE
320#define HAVE_TC_RAMCACHE 318#define HAVE_TC_RAMCACHE
321#endif 319#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 @@
22 22
23#include "config.h" 23#include "config.h"
24 24
25#ifdef HAVE_MULTIVOLUME
26
27/* how to name volumes, first char must be outside of legal file names,
28 a number gets appended to enumerate, if applicable */
29#ifdef HAVE_MMC
30#define VOL_NAMES "<MMC%d>"
31#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */
32#elif defined(HAVE_HOTSWAP)
33#define VOL_NAMES "<microSD%d>"
34#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */
35#else
36#define VOL_NAMES "<HD%d>"
37#define VOL_ENUM_POS 3
38#endif
39
40#endif
41
25#ifdef HAVE_DIRCACHE 42#ifdef HAVE_DIRCACHE
26# include "dircache.h" 43# include "dircache.h"
27# define DIR DIR_CACHED 44# 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 {
75char *get_volume_name(int volume); 75char *get_volume_name(int volume);
76#endif 76#endif
77 77
78#ifdef HAVE_MULTIVOLUME
79 int strip_volume(const char*, char*);
80#endif
81
78#ifndef DIRFUNCTIONS_DEFINED 82#ifndef DIRFUNCTIONS_DEFINED
79 83
80extern DIR_UNCACHED* opendir_uncached(const char* name); 84extern DIR_UNCACHED* opendir_uncached(const char* name);