diff options
author | Jörg Hohensohn <hohensoh@rockbox.org> | 2005-01-28 21:32:16 +0000 |
---|---|---|
committer | Jörg Hohensohn <hohensoh@rockbox.org> | 2005-01-28 21:32:16 +0000 |
commit | dc7534bdb2a784ae9d5c9089237935ff405c3525 (patch) | |
tree | e12e3eab71cbd72605d661ea026c70127d633cb3 /firmware/common | |
parent | 3662ad2ae3a9fb5ec5a7295bb606524e642bb840 (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware/common')
-rw-r--r-- | firmware/common/dir.c | 24 | ||||
-rw-r--r-- | firmware/common/disk.c | 97 | ||||
-rw-r--r-- | firmware/common/file.c | 20 |
3 files changed, 114 insertions, 27 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 | ||
72 | int 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 | |||
70 | DIR* opendir(const char* name) | 90 | DIR* 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 | ||
46 | static struct partinfo part[8]; /* space for 4 partitions on 2 drives */ | 48 | static struct partinfo part[8]; /* space for 4 partitions on 2 drives */ |
49 | static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */ | ||
47 | 50 | ||
48 | struct partinfo* disk_init(IF_MV_NONVOID(int drive)) | 51 | struct partinfo* disk_init(IF_MV_NONVOID(int drive)) |
49 | { | 52 | { |
@@ -95,46 +98,86 @@ struct partinfo* disk_partinfo(int partition) | |||
95 | 98 | ||
96 | int disk_mount_all(void) | 99 | int 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 | |||
119 | static 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 | |||
131 | int 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 */ | 165 | int 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 | ||
667 | int 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 */ | ||