diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2008-03-11 19:39:26 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2008-03-11 19:39:26 +0000 |
commit | 52d827a26dec8bc4967cf3c2984a10ace114fa21 (patch) | |
tree | 83b9660b904934a62df38ee0ed138c66f3cdebb1 /firmware | |
parent | afde7f74d4325c3a5a6883167c1f74f4fb689f90 (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/dir_uncached.c | 20 | ||||
-rw-r--r-- | firmware/common/dircache.c | 106 | ||||
-rw-r--r-- | firmware/export/config.h | 2 | ||||
-rw-r--r-- | firmware/include/dir.h | 17 | ||||
-rw-r--r-- | firmware/include/dir_uncached.h | 4 |
5 files changed, 101 insertions, 48 deletions
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 | ||
38 | static const char* vol_names = "<MMC%d>"; | ||
39 | #define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */ | ||
40 | #elif defined(HAVE_HOTSWAP) | ||
41 | static const char* vol_names = "<microSD%d>"; | ||
42 | #define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */ | ||
43 | #else | ||
44 | static 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) */ |
50 | static int strip_volume(const char* name, char* namecopy) | 36 | int 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 | ||
52 | static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; | 53 | static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; |
53 | static struct dircache_entry *dircache_root; | 54 | static struct dircache_entry *dircache_root; |
55 | #ifdef HAVE_MULTIVOLUME | ||
56 | static struct dircache_entry *append_position; | ||
57 | #endif | ||
54 | 58 | ||
55 | static bool dircache_initialized = false; | 59 | static bool dircache_initialized = false; |
56 | static bool dircache_initializing = false; | 60 | static 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 | */ |
169 | static int dircache_scan(struct travel_data *td) | 176 | static 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 |
276 | static int dircache_travel(DIR_UNCACHED *dir, struct dircache_entry *ce) | 283 | static int dircache_travel(IF_MV2(int volume,) DIR_UNCACHED *dir, struct dircache_entry *ce) |
277 | #else | 284 | #else |
278 | static int dircache_travel(struct fat_dir *dir, struct dircache_entry *ce) | 285 | static 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 { | |||
75 | char *get_volume_name(int volume); | 75 | char *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 | ||
80 | extern DIR_UNCACHED* opendir_uncached(const char* name); | 84 | extern DIR_UNCACHED* opendir_uncached(const char* name); |