summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2005-01-28 21:32:16 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2005-01-28 21:32:16 +0000
commitdc7534bdb2a784ae9d5c9089237935ff405c3525 (patch)
treee12e3eab71cbd72605d661ea026c70127d633cb3
parent3662ad2ae3a9fb5ec5a7295bb606524e642bb840 (diff)
downloadrockbox-dc7534bdb2a784ae9d5c9089237935ff405c3525.tar.gz
rockbox-dc7534bdb2a784ae9d5c9089237935ff405c3525.zip
preparations for hotswapping MMC
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5701 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/common/dir.c24
-rw-r--r--firmware/common/disk.c97
-rw-r--r--firmware/common/file.c20
-rw-r--r--firmware/drivers/fat.c4
-rw-r--r--firmware/export/disk.h2
-rw-r--r--firmware/include/dir.h2
-rw-r--r--firmware/include/file.h1
7 files changed, 121 insertions, 29 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index 4b4a5fa65d..aa55aeb9e9 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -67,6 +67,26 @@ static int strip_volume(const char* name, char* namecopy)
67#endif /* #ifdef HAVE_MULTIVOLUME */ 67#endif /* #ifdef HAVE_MULTIVOLUME */
68 68
69 69
70#ifdef HAVE_HOTSWAP
71// release all dir handles on a given volume "by force", to avoid leaks
72int release_dirs(int volume)
73{
74 DIR* pdir = opendirs;
75 int dd;
76 int closed = 0;
77 for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
78 {
79 if (pdir->fatdir.file.volume == volume)
80 {
81 pdir->busy = false; /* mark as available, no further action */
82 closed++;
83 }
84 }
85 return closed; /* return how many we did */
86}
87#endif /* #ifdef HAVE_HOTSWAP */
88
89
70DIR* opendir(const char* name) 90DIR* opendir(const char* name)
71{ 91{
72 char namecopy[MAX_PATH]; 92 char namecopy[MAX_PATH];
@@ -154,6 +174,10 @@ struct dirent* readdir(DIR* dir)
154{ 174{
155 struct fat_direntry entry; 175 struct fat_direntry entry;
156 struct dirent* theent = &(dir->theent); 176 struct dirent* theent = &(dir->theent);
177
178 if (!dir->busy)
179 return NULL;
180
157#ifdef HAVE_MULTIVOLUME 181#ifdef HAVE_MULTIVOLUME
158 /* Volumes (secondary file systems) get inserted into the root directory 182 /* Volumes (secondary file systems) get inserted into the root directory
159 of the first volume, since we have no separate top level. */ 183 of the first volume, since we have no separate top level. */
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index 923dffbe46..fd6de55ddb 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -23,6 +23,8 @@
23#ifdef HAVE_MMC 23#ifdef HAVE_MMC
24#include "ata_mmc.h" 24#include "ata_mmc.h"
25#endif 25#endif
26#include "file.h" /* for release_dirs() */
27#include "dir.h" /* for release_files() */
26#include "disk.h" 28#include "disk.h"
27 29
28/* Partition table entry layout: 30/* Partition table entry layout:
@@ -44,6 +46,7 @@
44 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) 46 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
45 47
46static struct partinfo part[8]; /* space for 4 partitions on 2 drives */ 48static struct partinfo part[8]; /* space for 4 partitions on 2 drives */
49static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */
47 50
48struct partinfo* disk_init(IF_MV_NONVOID(int drive)) 51struct partinfo* disk_init(IF_MV_NONVOID(int drive))
49{ 52{
@@ -95,46 +98,86 @@ struct partinfo* disk_partinfo(int partition)
95 98
96int disk_mount_all(void) 99int disk_mount_all(void)
97{ 100{
98 struct partinfo* pinfo; 101 int mounted;
99 int i,j; 102 int i;
100 int mounted = 0; 103
101 bool found; 104 fat_init(); /* reset all mounted partitions */
102 int drives = 1; 105 for (i=0; i<NUM_VOLUMES; i++)
106 vol_drive[i] = -1; /* mark all as unassigned */
107
108 mounted = disk_mount(0);
103#ifdef HAVE_MMC 109#ifdef HAVE_MMC
104 if (mmc_detect()) /* for Ondio, only if card detected */ 110 if (mmc_detect()) /* for Ondio, only if card detected */
105 { 111 {
106 drives = 2; /* in such case we have two drives to try */ 112 mounted += disk_mount(1); /* try 2nd "drive", too */
107 } 113 }
108#endif 114#endif
109 115
110 fat_init(); /* reset all mounted partitions */ 116 return mounted;
111 for (j=0; j<drives; j++) 117}
118
119static int get_free_volume(void)
120{
121 int i;
122 for (i=0; i<NUM_VOLUMES; i++)
123 {
124 if (vol_drive[i] == -1) /* unassigned? */
125 return i;
126 }
127
128 return -1; /* none found */
129}
130
131int disk_mount(int drive)
132{
133 int i;
134 int mounted = 0; /* reset partition-on-drive flag */
135 int volume = get_free_volume();
136 struct partinfo* pinfo = disk_init(IF_MV(drive));
137
138 if (pinfo == NULL)
139 {
140 return 0;
141 }
142 for (i=0; volume != -1 && i<4; i++)
112 { 143 {
113 found = false; /* reset partition-on-drive flag */ 144 if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) pinfo[i].start))
114 pinfo = disk_init(IF_MV(j));
115 if (pinfo == NULL)
116 { 145 {
117 continue; 146 mounted++;
147 vol_drive[volume] = drive; /* remember the drive for this volume */
148 volume = get_free_volume(); /* prepare next entry */
118 } 149 }
119 for (i=0; mounted<NUM_VOLUMES && i<4; i++) 150 }
151
152 if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */
153 { /* try "superfloppy" mode */
154 DEBUGF("No partition found, trying to mount sector 0.\n");
155 if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) 0))
120 { 156 {
121 if (!fat_mount(IF_MV2(mounted,) IF_MV2(j,) pinfo[i].start)) 157 mounted = 1;
122 { 158 vol_drive[volume] = drive; /* remember the drive for this volume */
123 mounted++;
124 found = true; /* at least one valid entry */
125 }
126 } 159 }
160 }
161 return mounted;
162}
127 163
128 if (!found && mounted<NUM_VOLUMES) /* none of the 4 entries worked? */ 164#ifdef HAVE_HOTSWAP
129 { /* try "superfloppy" mode */ 165int disk_unmount(int drive)
130 DEBUGF("No partition found, trying to mount sector 0.\n"); 166{
131 if (!fat_mount(IF_MV2(mounted,) IF_MV2(j,) 0)) 167 int unmounted = 0;
132 { 168 int i;
133 mounted++; 169 for (i=0; i<NUM_VOLUMES; i++)
134 } 170 {
171 if (vol_drive[i] == drive)
172 { /* force releasing resources */
173 vol_drive[i] = -1; /* mark unused */
174 unmounted++;
175 release_files(i);
176 release_dirs(i);
177 fat_unmount(i, false);
135 } 178 }
136 } 179 }
137 180
138 return mounted; 181 return unmounted;
139} 182}
140 183#endif /* #ifdef HAVE_HOTSWAP */
diff --git a/firmware/common/file.c b/firmware/common/file.c
index f04f787b45..795fc7df7e 100644
--- a/firmware/common/file.c
+++ b/firmware/common/file.c
@@ -660,3 +660,23 @@ off_t filesize(int fd)
660 660
661 return file->size; 661 return file->size;
662} 662}
663
664
665#ifdef HAVE_HOTSWAP
666// release all file handles on a given volume "by force", to avoid leaks
667int release_files(int volume)
668{
669 struct filedesc* pfile = openfiles;
670 int fd;
671 int closed = 0;
672 for ( fd=0; fd<MAX_OPEN_FILES; fd++, pfile++)
673 {
674 if (pfile->fatfile.volume == volume)
675 {
676 pfile->busy = false; /* mark as available, no further action */
677 closed++;
678 }
679 }
680 return closed; /* return how many we did */
681}
682#endif /* #ifdef HAVE_HOTSWAP */
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 3adca5e864..78aebd2e2b 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -482,7 +482,7 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector)
482 return 0; 482 return 0;
483} 483}
484 484
485#ifdef HAVE_MULTIVOLUME 485#ifdef HAVE_HOTSWAP
486int fat_unmount(int volume, bool flush) 486int fat_unmount(int volume, bool flush)
487{ 487{
488 int rc; 488 int rc;
@@ -511,7 +511,7 @@ int fat_unmount(int volume, bool flush)
511 fat_bpb->mounted = false; 511 fat_bpb->mounted = false;
512 return rc; 512 return rc;
513} 513}
514#endif 514#endif /* #ifdef HAVE_HOTSWAP */
515 515
516void fat_recalc_free(IF_MV_NONVOID(int volume)) 516void fat_recalc_free(IF_MV_NONVOID(int volume))
517{ 517{
diff --git a/firmware/export/disk.h b/firmware/export/disk.h
index e8525d1f75..e10fe9e7dc 100644
--- a/firmware/export/disk.h
+++ b/firmware/export/disk.h
@@ -35,5 +35,7 @@ struct partinfo {
35struct partinfo* disk_init(IF_MV_NONVOID(int volume)); 35struct partinfo* disk_init(IF_MV_NONVOID(int volume));
36struct partinfo* disk_partinfo(int partition); 36struct partinfo* disk_partinfo(int partition);
37int disk_mount_all(void); /* returns the # of successful mounts */ 37int disk_mount_all(void); /* returns the # of successful mounts */
38int disk_mount(int drive);
39int disk_unmount(int drive);
38 40
39#endif 41#endif
diff --git a/firmware/include/dir.h b/firmware/include/dir.h
index 5c157e4696..8dcbb8e900 100644
--- a/firmware/include/dir.h
+++ b/firmware/include/dir.h
@@ -84,6 +84,8 @@ extern int rmdir(const char* name);
84 84
85extern struct dirent* readdir(DIR* dir); 85extern struct dirent* readdir(DIR* dir);
86 86
87extern int release_dirs(int volume);
88
87#endif /* DIRFUNCTIONS_DEFINED */ 89#endif /* DIRFUNCTIONS_DEFINED */
88 90
89#endif 91#endif
diff --git a/firmware/include/file.h b/firmware/include/file.h
index e76abaaa96..387c34cdd8 100644
--- a/firmware/include/file.h
+++ b/firmware/include/file.h
@@ -87,6 +87,7 @@ extern int remove(const char* pathname);
87extern int rename(const char* path, const char* newname); 87extern int rename(const char* path, const char* newname);
88extern int ftruncate(int fd, off_t length); 88extern int ftruncate(int fd, off_t length);
89extern off_t filesize(int fd); 89extern off_t filesize(int fd);
90extern int release_files(int volume);
90#endif /* SIMULATOR */ 91#endif /* SIMULATOR */
91 92
92#endif 93#endif