diff options
Diffstat (limited to 'firmware/common/disk.c')
-rw-r--r-- | firmware/common/disk.c | 451 |
1 files changed, 297 insertions, 154 deletions
diff --git a/firmware/common/disk.c b/firmware/common/disk.c index 5a55a3b6ac..3a2d27e0d7 100644 --- a/firmware/common/disk.c +++ b/firmware/common/disk.c | |||
@@ -19,14 +19,25 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include <stdio.h> | 21 | #include <stdio.h> |
22 | #include <string.h> | ||
23 | #include "config.h" | ||
22 | #include "kernel.h" | 24 | #include "kernel.h" |
23 | #include "storage.h" | 25 | #include "storage.h" |
24 | #include "debug.h" | 26 | #include "debug.h" |
25 | #include "fat.h" | 27 | #include "disk_cache.h" |
26 | #include "dir.h" /* for release_dirs() */ | 28 | #include "fileobj_mgr.h" |
27 | #include "file.h" /* for release_files() */ | 29 | #include "dir.h" |
30 | #include "dircache_redirect.h" | ||
28 | #include "disk.h" | 31 | #include "disk.h" |
29 | #include <string.h> | 32 | |
33 | #ifndef CONFIG_DEFAULT_PARTNUM | ||
34 | #define CONFIG_DEFAULT_PARTNUM 0 | ||
35 | #endif | ||
36 | |||
37 | #define disk_reader_lock() file_internal_lock_READER() | ||
38 | #define disk_reader_unlock() file_internal_unlock_READER() | ||
39 | #define disk_writer_lock() file_internal_lock_WRITER() | ||
40 | #define disk_writer_unlock() file_internal_unlock_WRITER() | ||
30 | 41 | ||
31 | /* Partition table entry layout: | 42 | /* Partition table entry layout: |
32 | ----------------------- | 43 | ----------------------- |
@@ -42,11 +53,18 @@ | |||
42 | 12-15: nr of sectors in partition | 53 | 12-15: nr of sectors in partition |
43 | */ | 54 | */ |
44 | 55 | ||
45 | #define BYTES2INT32(array,pos) \ | 56 | #define BYTES2INT32(array, pos) \ |
46 | ((long)array[pos] | ((long)array[pos+1] << 8 ) | \ | 57 | (((uint32_t)array[pos+0] << 0) | \ |
47 | ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) | 58 | ((uint32_t)array[pos+1] << 8) | \ |
59 | ((uint32_t)array[pos+2] << 16) | \ | ||
60 | ((uint32_t)array[pos+3] << 24)) | ||
61 | |||
62 | #define BYTES2INT16(array, pos) \ | ||
63 | (((uint32_t)array[pos+0] << 0) | \ | ||
64 | ((uint32_t)array[pos+1] << 8)) | ||
48 | 65 | ||
49 | static const unsigned char fat_partition_types[] = { | 66 | static const unsigned char fat_partition_types[] = |
67 | { | ||
50 | 0x0b, 0x1b, /* FAT32 + hidden variant */ | 68 | 0x0b, 0x1b, /* FAT32 + hidden variant */ |
51 | 0x0c, 0x1c, /* FAT32 (LBA) + hidden variant */ | 69 | 0x0c, 0x1c, /* FAT32 (LBA) + hidden variant */ |
52 | #ifdef HAVE_FAT16SUPPORT | 70 | #ifdef HAVE_FAT16SUPPORT |
@@ -56,159 +74,135 @@ static const unsigned char fat_partition_types[] = { | |||
56 | #endif | 74 | #endif |
57 | }; | 75 | }; |
58 | 76 | ||
59 | static struct partinfo part[NUM_DRIVES*4]; /* space for 4 partitions on 2 drives */ | 77 | /* space for 4 partitions on 2 drives */ |
60 | static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */ | 78 | static struct partinfo part[NUM_DRIVES*4]; |
61 | static struct mutex disk_mutex; | 79 | /* mounted to which drive (-1 if none) */ |
80 | static int vol_drive[NUM_VOLUMES]; | ||
81 | |||
82 | static int get_free_volume(void) | ||
83 | { | ||
84 | for (int i = 0; i < NUM_VOLUMES; i++) | ||
85 | { | ||
86 | if (vol_drive[i] == -1) /* unassigned? */ | ||
87 | return i; | ||
88 | } | ||
89 | |||
90 | return -1; /* none found */ | ||
91 | } | ||
62 | 92 | ||
63 | #ifdef MAX_LOG_SECTOR_SIZE | 93 | #ifdef MAX_LOG_SECTOR_SIZE |
64 | static int disk_sector_multiplier[NUM_DRIVES] = {[0 ... NUM_DRIVES-1] = 1}; | 94 | static int disk_sector_multiplier[NUM_DRIVES] = |
95 | { [0 ... NUM_DRIVES-1] = 1 }; | ||
65 | 96 | ||
66 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)) | 97 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)) |
67 | { | 98 | { |
68 | #ifdef HAVE_MULTIDRIVE | 99 | if (!CHECK_DRV(drive)) |
69 | return disk_sector_multiplier[drive]; | 100 | return 0; |
70 | #else | 101 | |
71 | return disk_sector_multiplier[0]; | 102 | disk_reader_lock(); |
72 | #endif | 103 | int multiplier = disk_sector_multiplier[IF_MD_DRV(drive)]; |
104 | disk_reader_unlock(); | ||
105 | return multiplier; | ||
73 | } | 106 | } |
74 | #endif | 107 | #endif /* MAX_LOG_SECTOR_SIZE */ |
75 | 108 | ||
76 | struct partinfo* disk_init(IF_MD_NONVOID(int drive)) | 109 | bool disk_init(IF_MD_NONVOID(int drive)) |
77 | { | 110 | { |
78 | int i; | 111 | if (!CHECK_DRV(drive)) |
79 | #ifdef HAVE_MULTIDRIVE | 112 | return false; /* out of space in table */ |
80 | /* For each drive, start at a different position, in order not to destroy | ||
81 | the first entry of drive 0. | ||
82 | That one is needed to calculate config sector position. */ | ||
83 | struct partinfo* pinfo = &part[drive*4]; | ||
84 | if ((size_t)drive >= sizeof(part)/sizeof(*part)/4) | ||
85 | return NULL; /* out of space in table */ | ||
86 | #else | ||
87 | struct partinfo* pinfo = part; | ||
88 | const int drive = 0; | ||
89 | (void)drive; | ||
90 | #endif | ||
91 | 113 | ||
92 | unsigned char* sector = fat_get_sector_buffer(); | 114 | unsigned char *sector = dc_get_buffer(); |
93 | storage_read_sectors(IF_MD(drive,) 0,1, sector); | 115 | if (!sector) |
94 | /* check that the boot sector is initialized */ | 116 | return false; |
95 | if ( (sector[510] != 0x55) || | ||
96 | (sector[511] != 0xaa)) { | ||
97 | fat_release_sector_buffer(); | ||
98 | DEBUGF("Bad boot sector signature\n"); | ||
99 | return NULL; | ||
100 | } | ||
101 | 117 | ||
102 | /* parse partitions */ | 118 | memset(sector, 0, SECTOR_SIZE); |
103 | for ( i=0; i<4; i++ ) { | 119 | storage_read_sectors(IF_MD(drive,) 0, 1, sector); |
104 | unsigned char* ptr = sector + 0x1be + 16*i; | ||
105 | pinfo[i].type = ptr[4]; | ||
106 | pinfo[i].start = BYTES2INT32(ptr, 8); | ||
107 | pinfo[i].size = BYTES2INT32(ptr, 12); | ||
108 | 120 | ||
109 | DEBUGF("Part%d: Type %02x, start: %08lx size: %08lx\n", | 121 | bool init = false; |
110 | i,pinfo[i].type,pinfo[i].start,pinfo[i].size); | ||
111 | 122 | ||
112 | /* extended? */ | 123 | /* check that the boot sector is initialized */ |
113 | if ( pinfo[i].type == 5 ) { | 124 | if (BYTES2INT16(sector, 510) == 0xaa55) |
114 | /* not handled yet */ | 125 | { |
115 | } | 126 | /* For each drive, start at a different position, in order not to |
116 | } | 127 | destroy the first entry of drive 0. That one is needed to calculate |
117 | fat_release_sector_buffer(); | 128 | config sector position. */ |
118 | return pinfo; | 129 | struct partinfo *pinfo = &part[IF_MD_DRV(drive)*4]; |
119 | } | ||
120 | 130 | ||
121 | struct partinfo* disk_partinfo(int partition) | 131 | disk_writer_lock(); |
122 | { | ||
123 | return &part[partition]; | ||
124 | } | ||
125 | 132 | ||
126 | void disk_init_subsystem(void) | 133 | /* parse partitions */ |
127 | { | 134 | for (int i = 0; i < 4; i++) |
128 | mutex_init(&disk_mutex); | 135 | { |
129 | } | 136 | unsigned char* ptr = sector + 0x1be + 16*i; |
137 | pinfo[i].type = ptr[4]; | ||
138 | pinfo[i].start = BYTES2INT32(ptr, 8); | ||
139 | pinfo[i].size = BYTES2INT32(ptr, 12); | ||
130 | 140 | ||
131 | int disk_mount_all(void) | 141 | DEBUGF("Part%d: Type %02x, start: %08lx size: %08lx\n", |
132 | { | 142 | i,pinfo[i].type,pinfo[i].start,pinfo[i].size); |
133 | int mounted=0; | ||
134 | int i; | ||
135 | |||
136 | #ifdef HAVE_HOTSWAP | ||
137 | mutex_lock(&disk_mutex); | ||
138 | #endif | ||
139 | 143 | ||
140 | fat_init(); /* reset all mounted partitions */ | 144 | /* extended? */ |
141 | for (i=0; i<NUM_VOLUMES; i++) | 145 | if ( pinfo[i].type == 5 ) |
142 | vol_drive[i] = -1; /* mark all as unassigned */ | 146 | { |
147 | /* not handled yet */ | ||
148 | } | ||
149 | } | ||
143 | 150 | ||
144 | #ifndef HAVE_MULTIDRIVE | 151 | disk_writer_unlock(); |
145 | mounted = disk_mount(0); | 152 | |
146 | #else | 153 | init = true; |
147 | for(i=0;i<NUM_DRIVES;i++) | 154 | } |
155 | else | ||
148 | { | 156 | { |
149 | #ifdef HAVE_HOTSWAP | 157 | DEBUGF("Bad boot sector signature\n"); |
150 | if (storage_present(i)) | ||
151 | #endif | ||
152 | mounted += disk_mount(i); | ||
153 | } | 158 | } |
154 | #endif | ||
155 | 159 | ||
156 | #ifdef HAVE_HOTSWAP | 160 | dc_release_buffer(sector); |
157 | mutex_unlock(&disk_mutex); | 161 | return init; |
158 | #endif | ||
159 | return mounted; | ||
160 | } | 162 | } |
161 | 163 | ||
162 | static int get_free_volume(void) | 164 | bool disk_partinfo(int partition, struct partinfo *info) |
163 | { | 165 | { |
164 | int i; | 166 | if (partition < 0 || partition >= (int)ARRAYLEN(part) || !info) |
165 | for (i=0; i<NUM_VOLUMES; i++) | 167 | return false; |
166 | { | ||
167 | if (vol_drive[i] == -1) /* unassigned? */ | ||
168 | return i; | ||
169 | } | ||
170 | 168 | ||
171 | return -1; /* none found */ | 169 | disk_reader_lock(); |
170 | *info = part[partition]; | ||
171 | disk_reader_unlock(); | ||
172 | return true; | ||
172 | } | 173 | } |
173 | 174 | ||
174 | int disk_mount(int drive) | 175 | int disk_mount(int drive) |
175 | { | 176 | { |
176 | int mounted = 0; /* reset partition-on-drive flag */ | 177 | int mounted = 0; /* reset partition-on-drive flag */ |
177 | int volume; | ||
178 | struct partinfo* pinfo; | ||
179 | 178 | ||
180 | #ifdef HAVE_HOTSWAP | 179 | disk_writer_lock(); |
181 | mutex_lock(&disk_mutex); | ||
182 | #endif | ||
183 | 180 | ||
184 | volume = get_free_volume(); | 181 | int volume = get_free_volume(); |
185 | pinfo = disk_init(IF_MD(drive)); | ||
186 | #ifdef MAX_LOG_SECTOR_SIZE | ||
187 | disk_sector_multiplier[drive] = 1; | ||
188 | #endif | ||
189 | 182 | ||
190 | if (pinfo == NULL) | 183 | if (!disk_init(IF_MD(drive))) |
191 | { | 184 | { |
192 | #ifdef HAVE_HOTSWAP | 185 | disk_writer_unlock(); |
193 | mutex_unlock(&disk_mutex); | ||
194 | #endif | ||
195 | return 0; | 186 | return 0; |
196 | } | 187 | } |
197 | #if defined(TOSHIBA_GIGABEAT_S) | 188 | |
198 | int i = 1; /* For the Gigabeat S, we mount the second partition */ | 189 | struct partinfo *pinfo = &part[IF_MD_DRV(drive)*4]; |
199 | #else | 190 | #ifdef MAX_LOG_SECTOR_SIZE |
200 | int i = 0; | 191 | disk_sector_multiplier[IF_MD_DRV(drive)] = 1; |
201 | #endif | 192 | #endif |
202 | for (; volume != -1 && i<4 && mounted<NUM_VOLUMES_PER_DRIVE; i++) | 193 | |
194 | for (int i = CONFIG_DEFAULT_PARTNUM; | ||
195 | volume != -1 && i < 4 && mounted < NUM_VOLUMES_PER_DRIVE; | ||
196 | i++) | ||
203 | { | 197 | { |
204 | if (memchr(fat_partition_types, pinfo[i].type, | 198 | if (memchr(fat_partition_types, pinfo[i].type, |
205 | sizeof(fat_partition_types)) == NULL) | 199 | sizeof(fat_partition_types)) == NULL) |
206 | continue; /* not an accepted partition type */ | 200 | continue; /* not an accepted partition type */ |
207 | 201 | ||
208 | #ifdef MAX_LOG_SECTOR_SIZE | 202 | bool success = false; |
209 | int j; | 203 | |
210 | 204 | #ifdef MAX_LOG_SECTOR_SIZE | |
211 | for (j = 1; j <= (MAX_LOG_SECTOR_SIZE/SECTOR_SIZE); j <<= 1) | 205 | for (int j = 1; j <= (MAX_LOG_SECTOR_SIZE/SECTOR_SIZE); j <<= 1) |
212 | { | 206 | { |
213 | if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start * j)) | 207 | if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start * j)) |
214 | { | 208 | { |
@@ -218,93 +212,242 @@ int disk_mount(int drive) | |||
218 | vol_drive[volume] = drive; /* remember the drive for this volume */ | 212 | vol_drive[volume] = drive; /* remember the drive for this volume */ |
219 | volume = get_free_volume(); /* prepare next entry */ | 213 | volume = get_free_volume(); /* prepare next entry */ |
220 | disk_sector_multiplier[drive] = j; | 214 | disk_sector_multiplier[drive] = j; |
215 | success = true; | ||
221 | break; | 216 | break; |
222 | } | 217 | } |
223 | } | 218 | } |
224 | #else | 219 | #else /* ndef MAX_LOG_SECTOR_SIZE */ |
225 | if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start)) | 220 | if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start)) |
226 | { | 221 | { |
227 | mounted++; | 222 | mounted++; |
228 | vol_drive[volume] = drive; /* remember the drive for this volume */ | 223 | vol_drive[volume] = drive; /* remember the drive for this volume */ |
229 | volume = get_free_volume(); /* prepare next entry */ | 224 | volume = get_free_volume(); /* prepare next entry */ |
225 | success = true; | ||
230 | } | 226 | } |
231 | #endif | 227 | #endif /* MAX_LOG_SECTOR_SIZE */ |
228 | |||
229 | if (success) | ||
230 | volume_onmount_internal(IF_MV(volume)); | ||
232 | } | 231 | } |
233 | 232 | ||
234 | if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */ | 233 | if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */ |
235 | { /* try "superfloppy" mode */ | 234 | { /* try "superfloppy" mode */ |
236 | DEBUGF("No partition found, trying to mount sector 0.\n"); | 235 | DEBUGF("No partition found, trying to mount sector 0.\n"); |
236 | |||
237 | if (!fat_mount(IF_MV(volume,) IF_MD(drive,) 0)) | 237 | if (!fat_mount(IF_MV(volume,) IF_MD(drive,) 0)) |
238 | { | 238 | { |
239 | #ifdef MAX_LOG_SECTOR_SIZE | 239 | #ifdef MAX_LOG_SECTOR_SIZE |
240 | disk_sector_multiplier[drive] = fat_get_bytes_per_sector(IF_MV(volume))/SECTOR_SIZE; | 240 | disk_sector_multiplier[drive] = |
241 | #endif | 241 | fat_get_bytes_per_sector(IF_MV(volume)) / SECTOR_SIZE; |
242 | #endif | ||
242 | mounted = 1; | 243 | mounted = 1; |
243 | vol_drive[volume] = drive; /* remember the drive for this volume */ | 244 | vol_drive[volume] = drive; /* remember the drive for this volume */ |
245 | volume_onmount_internal(IF_MV(volume)); | ||
244 | } | 246 | } |
245 | } | 247 | } |
246 | #ifdef HAVE_HOTSWAP | 248 | |
247 | mutex_unlock(&disk_mutex); | 249 | disk_writer_unlock(); |
248 | #endif | 250 | return mounted; |
251 | } | ||
252 | |||
253 | int disk_mount_all(void) | ||
254 | { | ||
255 | int mounted = 0; | ||
256 | |||
257 | disk_writer_lock(); | ||
258 | |||
259 | /* reset all mounted partitions */ | ||
260 | volume_onunmount_internal(IF_MV(-1)); | ||
261 | fat_init(); | ||
262 | |||
263 | for (int i = 0; i < NUM_VOLUMES; i++) | ||
264 | vol_drive[i] = -1; /* mark all as unassigned */ | ||
265 | |||
266 | for (int i = 0; i < NUM_DRIVES; i++) | ||
267 | { | ||
268 | #ifdef HAVE_HOTSWAP | ||
269 | if (storage_present(i)) | ||
270 | #endif | ||
271 | mounted += disk_mount(i); | ||
272 | } | ||
273 | |||
274 | disk_writer_unlock(); | ||
249 | return mounted; | 275 | return mounted; |
250 | } | 276 | } |
251 | 277 | ||
252 | int disk_unmount(int drive) | 278 | int disk_unmount(int drive) |
253 | { | 279 | { |
280 | if (!CHECK_DRV(drive)) | ||
281 | return 0; | ||
282 | |||
254 | int unmounted = 0; | 283 | int unmounted = 0; |
255 | int i; | 284 | |
256 | #ifdef HAVE_HOTSWAP | 285 | disk_writer_lock(); |
257 | mutex_lock(&disk_mutex); | 286 | |
258 | #endif | 287 | for (int i = 0; i < NUM_VOLUMES; i++) |
259 | for (i=0; i<NUM_VOLUMES; i++) | ||
260 | { | 288 | { |
261 | if (vol_drive[i] == drive) | 289 | if (vol_drive[i] == drive) |
262 | { /* force releasing resources */ | 290 | { /* force releasing resources */ |
263 | vol_drive[i] = -1; /* mark unused */ | 291 | vol_drive[i] = -1; /* mark unused */ |
292 | |||
293 | volume_onunmount_internal(IF_MV(i)); | ||
294 | fat_unmount(IF_MV(i)); | ||
295 | |||
264 | unmounted++; | 296 | unmounted++; |
265 | release_files(i); | ||
266 | release_dirs(i); | ||
267 | fat_unmount(i, false); | ||
268 | } | 297 | } |
269 | } | 298 | } |
270 | #ifdef HAVE_HOTSWAP | ||
271 | mutex_unlock(&disk_mutex); | ||
272 | #endif | ||
273 | 299 | ||
300 | disk_writer_unlock(); | ||
274 | return unmounted; | 301 | return unmounted; |
275 | } | 302 | } |
276 | 303 | ||
277 | int disk_unmount_all(void) | 304 | int disk_unmount_all(void) |
278 | { | 305 | { |
279 | #ifndef HAVE_MULTIDRIVE | ||
280 | return disk_unmount(0); | ||
281 | #else /* HAVE_MULTIDRIVE */ | ||
282 | int unmounted = 0; | 306 | int unmounted = 0; |
283 | int i; | 307 | |
284 | for (i = 0; i < NUM_DRIVES; i++) | 308 | disk_writer_lock(); |
309 | |||
310 | volume_onunmount_internal(IF_MV(-1)); | ||
311 | |||
312 | for (int i = 0; i < NUM_DRIVES; i++) | ||
285 | { | 313 | { |
286 | #ifdef HAVE_HOTSWAP | 314 | #ifdef HAVE_HOTSWAP |
287 | if (storage_present(i)) | 315 | if (storage_present(i)) |
288 | #endif | 316 | #endif |
289 | unmounted += disk_unmount(i); | 317 | unmounted += disk_unmount(i); |
290 | } | 318 | } |
291 | 319 | ||
320 | disk_writer_unlock(); | ||
292 | return unmounted; | 321 | return unmounted; |
293 | #endif /* HAVE_MULTIDRIVE */ | 322 | } |
323 | |||
324 | bool disk_present(IF_MD_NONVOID(int drive)) | ||
325 | { | ||
326 | int rc = -1; | ||
327 | |||
328 | if (CHECK_DRV(drive)) | ||
329 | { | ||
330 | void *sector = dc_get_buffer(); | ||
331 | if (sector) | ||
332 | { | ||
333 | rc = storage_read_sectors(IF_MD(drive,) 0, 1, sector); | ||
334 | dc_release_buffer(sector); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | return rc == 0; | ||
339 | } | ||
340 | |||
341 | |||
342 | /** Volume-centric functions **/ | ||
343 | |||
344 | void volume_recalc_free(IF_MV_NONVOID(int volume)) | ||
345 | { | ||
346 | if (!CHECK_VOL(volume)) | ||
347 | return; | ||
348 | |||
349 | /* FIXME: this is crummy but the only way to ensure a correct freecount | ||
350 | if other threads are writing and changing the fsinfo; it is possible | ||
351 | to get multiple threads calling here and also writing and get correct | ||
352 | freespace counts, however a bit complicated to do; if thou desireth I | ||
353 | shall implement the concurrent version -- jethead71 */ | ||
354 | disk_writer_lock(); | ||
355 | fat_recalc_free(IF_MV(volume)); | ||
356 | disk_writer_unlock(); | ||
357 | } | ||
358 | |||
359 | unsigned int volume_get_cluster_size(IF_MV_NONVOID(int volume)) | ||
360 | { | ||
361 | if (!CHECK_VOL(volume)) | ||
362 | return 0; | ||
363 | |||
364 | disk_reader_lock(); | ||
365 | unsigned int clustersize = fat_get_cluster_size(IF_MV(volume)); | ||
366 | disk_reader_unlock(); | ||
367 | return clustersize; | ||
368 | } | ||
369 | |||
370 | void volume_size(IF_MV(int volume,) unsigned long *sizep, unsigned long *freep) | ||
371 | { | ||
372 | disk_reader_lock(); | ||
373 | |||
374 | if (!CHECK_VOL(volume) || !fat_size(IF_MV(volume,) sizep, freep)) | ||
375 | { | ||
376 | if (freep) *sizep = 0; | ||
377 | if (freep) *freep = 0; | ||
378 | } | ||
379 | |||
380 | disk_reader_unlock(); | ||
381 | } | ||
382 | |||
383 | #if defined (HAVE_HOTSWAP) || defined (HAVE_MULTIDRIVE) \ | ||
384 | || defined (HAVE_DIRCACHE) | ||
385 | enum volume_info_type | ||
386 | { | ||
387 | #ifdef HAVE_HOTSWAP | ||
388 | VP_REMOVABLE, | ||
389 | VP_PRESENT, | ||
390 | #endif | ||
391 | #if defined (HAVE_MULTIDRIVE) || defined (HAVE_DIRCACHE) | ||
392 | VP_DRIVE, | ||
393 | #endif | ||
394 | }; | ||
395 | |||
396 | static int volume_properties(int volume, enum volume_info_type infotype) | ||
397 | { | ||
398 | int res = -1; | ||
399 | |||
400 | disk_reader_lock(); | ||
401 | |||
402 | if (CHECK_VOL(volume)) | ||
403 | { | ||
404 | int vd = vol_drive[volume]; | ||
405 | switch (infotype) | ||
406 | { | ||
407 | #ifdef HAVE_HOTSWAP | ||
408 | case VP_REMOVABLE: | ||
409 | res = storage_removable(vd) ? 1 : 0; | ||
410 | break; | ||
411 | case VP_PRESENT: | ||
412 | res = storage_present(vd) ? 1 : 0; | ||
413 | break; | ||
414 | #endif | ||
415 | #if defined(HAVE_MULTIDRIVE) || defined(HAVE_DIRCACHE) | ||
416 | case VP_DRIVE: | ||
417 | res = vd; | ||
418 | break; | ||
419 | #endif | ||
420 | } | ||
421 | } | ||
422 | |||
423 | disk_reader_unlock(); | ||
424 | return res; | ||
294 | } | 425 | } |
295 | 426 | ||
296 | #ifdef HAVE_HOTSWAP | 427 | #ifdef HAVE_HOTSWAP |
297 | bool volume_removable(int volume) | 428 | bool volume_removable(int volume) |
298 | { | 429 | { |
299 | if(vol_drive[volume] == -1) | 430 | return volume_properties(volume, VP_REMOVABLE) > 0; |
300 | return false; | ||
301 | return storage_removable(vol_drive[volume]); | ||
302 | } | 431 | } |
303 | 432 | ||
304 | bool volume_present(int volume) | 433 | bool volume_present(int volume) |
305 | { | 434 | { |
306 | if(vol_drive[volume] == -1) | 435 | return volume_properties(volume, VP_PRESENT) > 0; |
307 | return false; | ||
308 | return storage_present(vol_drive[volume]); | ||
309 | } | 436 | } |
310 | #endif | 437 | #endif /* HAVE_HOTSWAP */ |
438 | |||
439 | #ifdef HAVE_MULTIDRIVE | ||
440 | int volume_drive(int volume) | ||
441 | { | ||
442 | return volume_properties(volume, VP_DRIVE); | ||
443 | } | ||
444 | #endif /* HAVE_MULTIDRIVE */ | ||
445 | |||
446 | #ifdef HAVE_DIRCACHE | ||
447 | bool volume_ismounted(IF_MV_NONVOID(int volume)) | ||
448 | { | ||
449 | return volume_properties(IF_MV_VOL(volume), VP_DRIVE) >= 0; | ||
450 | } | ||
451 | #endif /* HAVE_DIRCACHE */ | ||
452 | |||
453 | #endif /* HAVE_HOTSWAP || HAVE_MULTIDRIVE || HAVE_DIRCACHE */ | ||