diff options
author | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-12-28 22:16:07 +0000 |
---|---|---|
committer | Jörg Hohensohn <hohensoh@rockbox.org> | 2004-12-28 22:16:07 +0000 |
commit | da848576312800dc229624e928d132d0702c1854 (patch) | |
tree | 38cd01b8a9c1069a1de734e0f7eb478436715573 /firmware/drivers | |
parent | ae45d970d874217b779071b414dcd5edbf5647da (diff) | |
download | rockbox-da848576312800dc229624e928d132d0702c1854.tar.gz rockbox-da848576312800dc229624e928d132d0702c1854.zip |
prepared to mount multiple partitions into one logical file system (most useful for Ondio, internal memory + external MMC)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5514 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/ata.c | 11 | ||||
-rw-r--r-- | firmware/drivers/ata_mmc.c | 32 | ||||
-rw-r--r-- | firmware/drivers/fat.c | 734 |
3 files changed, 488 insertions, 289 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 9a0476f5cc..349ba077dd 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -310,7 +310,8 @@ static void copy_read_sectors(unsigned char* buf, int wordcount) | |||
310 | #endif | 310 | #endif |
311 | } | 311 | } |
312 | 312 | ||
313 | int ata_read_sectors(unsigned long start, | 313 | int ata_read_sectors(IF_MV((int drive,)) |
314 | unsigned long start, | ||
314 | int incount, | 315 | int incount, |
315 | void* inbuf) | 316 | void* inbuf) |
316 | { | 317 | { |
@@ -576,7 +577,8 @@ static void copy_write_sectors(const unsigned char* buf, int wordcount) | |||
576 | #endif | 577 | #endif |
577 | } | 578 | } |
578 | 579 | ||
579 | int ata_write_sectors(unsigned long start, | 580 | int ata_write_sectors(IF_MV((int drive,)) |
581 | unsigned long start, | ||
580 | int count, | 582 | int count, |
581 | const void* buf) | 583 | const void* buf) |
582 | { | 584 | { |
@@ -669,6 +671,8 @@ int ata_write_sectors(unsigned long start, | |||
669 | return ret; | 671 | return ret; |
670 | } | 672 | } |
671 | 673 | ||
674 | /* schedule a single sector write, executed with the the next spinup | ||
675 | (volume 0 only, used for config sector) */ | ||
672 | extern void ata_delayed_write(unsigned long sector, const void* buf) | 676 | extern void ata_delayed_write(unsigned long sector, const void* buf) |
673 | { | 677 | { |
674 | memcpy(delayed_sector, buf, SECTOR_SIZE); | 678 | memcpy(delayed_sector, buf, SECTOR_SIZE); |
@@ -676,12 +680,13 @@ extern void ata_delayed_write(unsigned long sector, const void* buf) | |||
676 | delayed_write = true; | 680 | delayed_write = true; |
677 | } | 681 | } |
678 | 682 | ||
683 | /* write the delayed sector to volume 0 */ | ||
679 | extern void ata_flush(void) | 684 | extern void ata_flush(void) |
680 | { | 685 | { |
681 | if ( delayed_write ) { | 686 | if ( delayed_write ) { |
682 | DEBUGF("ata_flush()\n"); | 687 | DEBUGF("ata_flush()\n"); |
683 | delayed_write = false; | 688 | delayed_write = false; |
684 | ata_write_sectors(delayed_sector_num, 1, delayed_sector); | 689 | ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector); |
685 | } | 690 | } |
686 | } | 691 | } |
687 | 692 | ||
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c index a61d28cb07..d75309547f 100644 --- a/firmware/drivers/ata_mmc.c +++ b/firmware/drivers/ata_mmc.c | |||
@@ -608,17 +608,24 @@ static int send_single_sector(const unsigned char *buf, int timeout) | |||
608 | return ret; | 608 | return ret; |
609 | } | 609 | } |
610 | 610 | ||
611 | int ata_read_sectors(unsigned long start, | 611 | int ata_read_sectors( |
612 | int incount, | 612 | #ifdef HAVE_MULTIVOLUME |
613 | void* inbuf) | 613 | int drive, |
614 | #endif | ||
615 | unsigned long start, | ||
616 | int incount, | ||
617 | void* inbuf) | ||
614 | { | 618 | { |
615 | int ret = 0; | 619 | int ret = 0; |
616 | int i; | 620 | int i; |
617 | unsigned long addr; | 621 | unsigned long addr; |
618 | unsigned char response; | 622 | unsigned char response; |
619 | void *inbuf_prev = NULL; | 623 | void *inbuf_prev = NULL; |
620 | tCardInfo *card = &card_info[current_card]; | 624 | tCardInfo *card; |
621 | 625 | #ifdef HAVE_MULTIVOLUME | |
626 | current_card = drive; | ||
627 | #endif | ||
628 | card = &card_info[current_card]; | ||
622 | addr = start * SECTOR_SIZE; | 629 | addr = start * SECTOR_SIZE; |
623 | 630 | ||
624 | mutex_lock(&mmc_mutex); | 631 | mutex_lock(&mmc_mutex); |
@@ -663,7 +670,11 @@ int ata_read_sectors(unsigned long start, | |||
663 | return ret; | 670 | return ret; |
664 | } | 671 | } |
665 | 672 | ||
666 | int ata_write_sectors(unsigned long start, | 673 | int ata_write_sectors( |
674 | #ifdef HAVE_MULTIVOLUME | ||
675 | int drive, | ||
676 | #endif | ||
677 | unsigned long start, | ||
667 | int count, | 678 | int count, |
668 | const void* buf) | 679 | const void* buf) |
669 | { | 680 | { |
@@ -671,7 +682,11 @@ int ata_write_sectors(unsigned long start, | |||
671 | int i; | 682 | int i; |
672 | unsigned long addr; | 683 | unsigned long addr; |
673 | unsigned char response; | 684 | unsigned char response; |
674 | tCardInfo *card = &card_info[current_card]; | 685 | tCardInfo *card; |
686 | #ifdef HAVE_MULTIVOLUME | ||
687 | current_card = drive; | ||
688 | #endif | ||
689 | card = &card_info[current_card]; | ||
675 | 690 | ||
676 | if (start == 0) | 691 | if (start == 0) |
677 | panicf("Writing on sector 0\n"); | 692 | panicf("Writing on sector 0\n"); |
@@ -733,12 +748,13 @@ extern void ata_delayed_write(unsigned long sector, const void* buf) | |||
733 | delayed_write = true; | 748 | delayed_write = true; |
734 | } | 749 | } |
735 | 750 | ||
751 | /* write the delayed sector to volume 0 */ | ||
736 | extern void ata_flush(void) | 752 | extern void ata_flush(void) |
737 | { | 753 | { |
738 | if ( delayed_write ) { | 754 | if ( delayed_write ) { |
739 | DEBUGF("ata_flush()\n"); | 755 | DEBUGF("ata_flush()\n"); |
740 | delayed_write = false; | 756 | delayed_write = false; |
741 | ata_write_sectors(delayed_sector_num, 1, delayed_sector); | 757 | ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector); |
742 | } | 758 | } |
743 | } | 759 | } |
744 | 760 | ||
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 9519ea9825..f0865eb985 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -219,17 +219,21 @@ struct bpb | |||
219 | bool is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */ | 219 | bool is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */ |
220 | unsigned int rootdirsectors; /* fixed # of sectors occupied by root dir */ | 220 | unsigned int rootdirsectors; /* fixed # of sectors occupied by root dir */ |
221 | #endif /* #ifdef HAVE_FAT16SUPPORT */ | 221 | #endif /* #ifdef HAVE_FAT16SUPPORT */ |
222 | #ifdef HAVE_MULTIVOLUME | ||
223 | int drive; /* on which physical device is this located */ | ||
224 | bool mounted; /* flag if this volume is mounted */ | ||
225 | #endif | ||
222 | }; | 226 | }; |
223 | 227 | ||
224 | static struct bpb fat_bpb; | 228 | static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */ |
225 | 229 | ||
226 | static int update_fsinfo(void); | 230 | static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)); |
227 | static int first_sector_of_cluster(int cluster); | 231 | static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb)); |
228 | static int bpb_is_sane(void); | 232 | static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster); |
229 | static void *cache_fat_sector(int secnum); | 233 | static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int secnum); |
230 | static int create_dos_name(const unsigned char *name, unsigned char *newname); | 234 | static int create_dos_name(const unsigned char *name, unsigned char *newname); |
231 | static unsigned int find_free_cluster(unsigned int start); | 235 | static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int start); |
232 | static int transfer( unsigned int start, int count, char* buf, bool write ); | 236 | static int transfer(IF_MV2(struct bpb* fat_bpb,) unsigned int start, int count, char* buf, bool write ); |
233 | 237 | ||
234 | #define FAT_CACHE_SIZE 0x20 | 238 | #define FAT_CACHE_SIZE 0x20 |
235 | #define FAT_CACHE_MASK (FAT_CACHE_SIZE-1) | 239 | #define FAT_CACHE_MASK (FAT_CACHE_SIZE-1) |
@@ -239,26 +243,35 @@ struct fat_cache_entry | |||
239 | int secnum; | 243 | int secnum; |
240 | bool inuse; | 244 | bool inuse; |
241 | bool dirty; | 245 | bool dirty; |
246 | #ifdef HAVE_MULTIVOLUME | ||
247 | struct bpb* fat_vol ; /* shared cache for all volumes */ | ||
248 | #endif | ||
242 | }; | 249 | }; |
243 | 250 | ||
244 | static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE]; | 251 | static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE]; |
245 | static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; | 252 | static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; |
246 | 253 | ||
247 | static int sec2cluster(unsigned int sec) | 254 | static int sec2cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int sec) |
248 | { | 255 | { |
249 | if ( sec < fat_bpb.firstdatasector ) | 256 | #ifndef HAVE_MULTIVOLUME |
257 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
258 | #endif | ||
259 | if ( sec < fat_bpb->firstdatasector ) | ||
250 | { | 260 | { |
251 | DEBUGF( "sec2cluster() - Bad sector number (%d)\n", sec); | 261 | DEBUGF( "sec2cluster() - Bad sector number (%d)\n", sec); |
252 | return -1; | 262 | return -1; |
253 | } | 263 | } |
254 | 264 | ||
255 | return ((sec - fat_bpb.firstdatasector) / fat_bpb.bpb_secperclus) + 2; | 265 | return ((sec - fat_bpb->firstdatasector) / fat_bpb->bpb_secperclus) + 2; |
256 | } | 266 | } |
257 | 267 | ||
258 | static int cluster2sec(int cluster) | 268 | static int cluster2sec(IF_MV2(struct bpb* fat_bpb,) int cluster) |
259 | { | 269 | { |
260 | int max_cluster = fat_bpb.totalsectors - | 270 | #ifndef HAVE_MULTIVOLUME |
261 | fat_bpb.firstdatasector / fat_bpb.bpb_secperclus + 1; | 271 | struct bpb* fat_bpb = &fat_bpbs[0]; |
272 | #endif | ||
273 | int max_cluster = fat_bpb->totalsectors - | ||
274 | fat_bpb->firstdatasector / fat_bpb->bpb_secperclus + 1; | ||
262 | 275 | ||
263 | if(cluster > max_cluster) | 276 | if(cluster > max_cluster) |
264 | { | 277 | { |
@@ -267,109 +280,141 @@ static int cluster2sec(int cluster) | |||
267 | return -1; | 280 | return -1; |
268 | } | 281 | } |
269 | 282 | ||
270 | return first_sector_of_cluster(cluster); | 283 | return first_sector_of_cluster(IF_MV2(fat_bpb,) cluster); |
271 | } | 284 | } |
272 | 285 | ||
273 | static int first_sector_of_cluster(int cluster) | 286 | static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster) |
274 | { | 287 | { |
288 | #ifndef HAVE_MULTIVOLUME | ||
289 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
290 | #endif | ||
275 | #ifdef HAVE_FAT16SUPPORT | 291 | #ifdef HAVE_FAT16SUPPORT |
276 | /* negative clusters (FAT16 root dir) don't get the 2 offset */ | 292 | /* negative clusters (FAT16 root dir) don't get the 2 offset */ |
277 | int zerocluster = cluster < 0 ? 0 : 2; | 293 | int zerocluster = cluster < 0 ? 0 : 2; |
278 | #else | 294 | #else |
279 | const int zerocluster = 2; | 295 | const int zerocluster = 2; |
280 | #endif | 296 | #endif |
281 | return (cluster - zerocluster) * fat_bpb.bpb_secperclus + fat_bpb.firstdatasector; | 297 | return (cluster - zerocluster) * fat_bpb->bpb_secperclus + fat_bpb->firstdatasector; |
282 | } | 298 | } |
283 | 299 | ||
284 | int fat_startsector(void) | 300 | int fat_startsector(IF_MV_NONVOID(int volume)) |
285 | { | 301 | { |
286 | return fat_bpb.startsector; | 302 | #ifndef HAVE_MULTIVOLUME |
303 | const int volume = 0; | ||
304 | #endif | ||
305 | struct bpb* fat_bpb = &fat_bpbs[volume]; | ||
306 | return fat_bpb->startsector; | ||
287 | } | 307 | } |
288 | 308 | ||
289 | void fat_size(unsigned int* size, unsigned int* free) | 309 | void fat_size(IF_MV2(int volume,) unsigned int* size, unsigned int* free) |
290 | { | 310 | { |
311 | #ifndef HAVE_MULTIVOLUME | ||
312 | const int volume = 0; | ||
313 | #endif | ||
314 | struct bpb* fat_bpb = &fat_bpbs[volume]; | ||
291 | if (size) | 315 | if (size) |
292 | *size = fat_bpb.dataclusters * fat_bpb.bpb_secperclus / 2; | 316 | *size = fat_bpb->dataclusters * fat_bpb->bpb_secperclus / 2; |
293 | if (free) | 317 | if (free) |
294 | *free = fat_bpb.fsinfo.freecount * fat_bpb.bpb_secperclus / 2; | 318 | *free = fat_bpb->fsinfo.freecount * fat_bpb->bpb_secperclus / 2; |
295 | } | 319 | } |
296 | 320 | ||
297 | int fat_mount(int startsector) | 321 | void fat_init(void) |
298 | { | 322 | { |
299 | unsigned char buf[SECTOR_SIZE]; | ||
300 | int rc; | ||
301 | int datasec; | ||
302 | unsigned int i; | 323 | unsigned int i; |
303 | 324 | /* mark the FAT cache as unused */ | |
304 | for(i = 0;i < FAT_CACHE_SIZE;i++) | 325 | for(i = 0;i < FAT_CACHE_SIZE;i++) |
305 | { | 326 | { |
306 | fat_cache[i].secnum = 8; /* We use a "safe" sector just in case */ | 327 | fat_cache[i].secnum = 8; /* We use a "safe" sector just in case */ |
307 | fat_cache[i].inuse = false; | 328 | fat_cache[i].inuse = false; |
308 | fat_cache[i].dirty = false; | 329 | fat_cache[i].dirty = false; |
330 | #ifdef HAVE_MULTIVOLUME | ||
331 | fat_cache[i].fat_vol = NULL; | ||
332 | #endif | ||
333 | } | ||
334 | #ifdef HAVE_MULTIVOLUME | ||
335 | /* mark the possible volumes as not mounted */ | ||
336 | for (i=0; i<NUM_VOLUMES;i++) | ||
337 | { | ||
338 | fat_bpbs[i].mounted = false; | ||
309 | } | 339 | } |
340 | #endif | ||
341 | } | ||
342 | |||
343 | int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector) | ||
344 | { | ||
345 | #ifndef HAVE_MULTIVOLUME | ||
346 | const int volume = 0; | ||
347 | #endif | ||
348 | struct bpb* fat_bpb = &fat_bpbs[volume]; | ||
349 | unsigned char buf[SECTOR_SIZE]; | ||
350 | int rc; | ||
351 | int datasec; | ||
310 | 352 | ||
311 | /* Read the sector */ | 353 | /* Read the sector */ |
312 | rc = ata_read_sectors(startsector,1,buf); | 354 | rc = ata_read_sectors(IF_MV2(drive,) startsector,1,buf); |
313 | if(rc) | 355 | if(rc) |
314 | { | 356 | { |
315 | DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", rc); | 357 | DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", rc); |
316 | return rc * 10 - 1; | 358 | return rc * 10 - 1; |
317 | } | 359 | } |
318 | 360 | ||
319 | memset(&fat_bpb, 0, sizeof(struct bpb)); | 361 | memset(fat_bpb, 0, sizeof(struct bpb)); |
320 | fat_bpb.startsector = startsector; | 362 | fat_bpb->startsector = startsector; |
321 | 363 | #ifdef HAVE_MULTIVOLUME | |
322 | fat_bpb.bpb_bytspersec = BYTES2INT16(buf,BPB_BYTSPERSEC); | 364 | fat_bpb->drive = drive; |
323 | fat_bpb.bpb_secperclus = buf[BPB_SECPERCLUS]; | 365 | #endif |
324 | fat_bpb.bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT); | 366 | |
325 | fat_bpb.bpb_numfats = buf[BPB_NUMFATS]; | 367 | fat_bpb->bpb_bytspersec = BYTES2INT16(buf,BPB_BYTSPERSEC); |
326 | fat_bpb.bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); | 368 | fat_bpb->bpb_secperclus = buf[BPB_SECPERCLUS]; |
327 | fat_bpb.bpb_media = buf[BPB_MEDIA]; | 369 | fat_bpb->bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT); |
328 | fat_bpb.bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); | 370 | fat_bpb->bpb_numfats = buf[BPB_NUMFATS]; |
329 | fat_bpb.bpb_fatsz32 = BYTES2INT32(buf,BPB_FATSZ32); | 371 | fat_bpb->bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); |
330 | fat_bpb.bpb_totsec32 = BYTES2INT32(buf,BPB_TOTSEC32); | 372 | fat_bpb->bpb_media = buf[BPB_MEDIA]; |
331 | fat_bpb.last_word = BYTES2INT16(buf,BPB_LAST_WORD); | 373 | fat_bpb->bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); |
374 | fat_bpb->bpb_fatsz32 = BYTES2INT32(buf,BPB_FATSZ32); | ||
375 | fat_bpb->bpb_totsec32 = BYTES2INT32(buf,BPB_TOTSEC32); | ||
376 | fat_bpb->last_word = BYTES2INT16(buf,BPB_LAST_WORD); | ||
332 | 377 | ||
333 | /* calculate a few commonly used values */ | 378 | /* calculate a few commonly used values */ |
334 | if (fat_bpb.bpb_fatsz16 != 0) | 379 | if (fat_bpb->bpb_fatsz16 != 0) |
335 | fat_bpb.fatsize = fat_bpb.bpb_fatsz16; | 380 | fat_bpb->fatsize = fat_bpb->bpb_fatsz16; |
336 | else | 381 | else |
337 | fat_bpb.fatsize = fat_bpb.bpb_fatsz32; | 382 | fat_bpb->fatsize = fat_bpb->bpb_fatsz32; |
338 | 383 | ||
339 | if (fat_bpb.bpb_totsec16 != 0) | 384 | if (fat_bpb->bpb_totsec16 != 0) |
340 | fat_bpb.totalsectors = fat_bpb.bpb_totsec16; | 385 | fat_bpb->totalsectors = fat_bpb->bpb_totsec16; |
341 | else | 386 | else |
342 | fat_bpb.totalsectors = fat_bpb.bpb_totsec32; | 387 | fat_bpb->totalsectors = fat_bpb->bpb_totsec32; |
343 | 388 | ||
344 | #ifdef HAVE_FAT16SUPPORT | 389 | #ifdef HAVE_FAT16SUPPORT |
345 | fat_bpb.bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT); | 390 | fat_bpb->bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT); |
346 | fat_bpb.rootdirsectors = ((fat_bpb.bpb_rootentcnt * 32) | 391 | fat_bpb->rootdirsectors = ((fat_bpb->bpb_rootentcnt * 32) |
347 | + (fat_bpb.bpb_bytspersec - 1)) / fat_bpb.bpb_bytspersec; | 392 | + (fat_bpb->bpb_bytspersec - 1)) / fat_bpb->bpb_bytspersec; |
348 | #endif /* #ifdef HAVE_FAT16SUPPORT */ | 393 | #endif /* #ifdef HAVE_FAT16SUPPORT */ |
349 | 394 | ||
350 | fat_bpb.firstdatasector = fat_bpb.bpb_rsvdseccnt | 395 | fat_bpb->firstdatasector = fat_bpb->bpb_rsvdseccnt |
351 | #ifdef HAVE_FAT16SUPPORT | 396 | #ifdef HAVE_FAT16SUPPORT |
352 | + fat_bpb.rootdirsectors | 397 | + fat_bpb->rootdirsectors |
353 | #endif | 398 | #endif |
354 | + fat_bpb.bpb_numfats * fat_bpb.fatsize; | 399 | + fat_bpb->bpb_numfats * fat_bpb->fatsize; |
355 | 400 | ||
356 | /* Determine FAT type */ | 401 | /* Determine FAT type */ |
357 | datasec = fat_bpb.totalsectors - fat_bpb.firstdatasector; | 402 | datasec = fat_bpb->totalsectors - fat_bpb->firstdatasector; |
358 | fat_bpb.dataclusters = datasec / fat_bpb.bpb_secperclus; | 403 | fat_bpb->dataclusters = datasec / fat_bpb->bpb_secperclus; |
359 | 404 | ||
360 | #ifdef TEST_FAT | 405 | #ifdef TEST_FAT |
361 | /* | 406 | /* |
362 | we are sometimes testing with "illegally small" fat32 images, | 407 | we are sometimes testing with "illegally small" fat32 images, |
363 | so we don't use the proper fat32 test case for test code | 408 | so we don't use the proper fat32 test case for test code |
364 | */ | 409 | */ |
365 | if ( fat_bpb.bpb_fatsz16 ) | 410 | if ( fat_bpb->bpb_fatsz16 ) |
366 | #else | 411 | #else |
367 | if ( fat_bpb.dataclusters < 65525 ) | 412 | if ( fat_bpb->dataclusters < 65525 ) |
368 | #endif | 413 | #endif |
369 | { /* FAT16 */ | 414 | { /* FAT16 */ |
370 | #ifdef HAVE_FAT16SUPPORT | 415 | #ifdef HAVE_FAT16SUPPORT |
371 | fat_bpb.is_fat16 = true; | 416 | fat_bpb->is_fat16 = true; |
372 | if (fat_bpb.dataclusters < 4085) | 417 | if (fat_bpb->dataclusters < 4085) |
373 | { /* FAT12 */ | 418 | { /* FAT12 */ |
374 | DEBUGF("This is FAT12. Go away!\n"); | 419 | DEBUGF("This is FAT12. Go away!\n"); |
375 | return -2; | 420 | return -2; |
@@ -381,26 +426,26 @@ int fat_mount(int startsector) | |||
381 | } | 426 | } |
382 | 427 | ||
383 | #ifdef HAVE_FAT16SUPPORT | 428 | #ifdef HAVE_FAT16SUPPORT |
384 | if (fat_bpb.is_fat16) | 429 | if (fat_bpb->is_fat16) |
385 | { /* FAT16 specific part of BPB */ | 430 | { /* FAT16 specific part of BPB */ |
386 | int dirclusters; | 431 | int dirclusters; |
387 | fat_bpb.rootdirsector = fat_bpb.bpb_rsvdseccnt | 432 | fat_bpb->rootdirsector = fat_bpb->bpb_rsvdseccnt |
388 | + fat_bpb.bpb_numfats * fat_bpb.bpb_fatsz16; | 433 | + fat_bpb->bpb_numfats * fat_bpb->bpb_fatsz16; |
389 | dirclusters = ((fat_bpb.rootdirsectors + fat_bpb.bpb_secperclus - 1) | 434 | dirclusters = ((fat_bpb->rootdirsectors + fat_bpb->bpb_secperclus - 1) |
390 | / fat_bpb.bpb_secperclus); /* rounded up, to full clusters */ | 435 | / fat_bpb->bpb_secperclus); /* rounded up, to full clusters */ |
391 | /* I assign negative pseudo cluster numbers for the root directory, | 436 | /* I assign negative pseudo cluster numbers for the root directory, |
392 | their range is counted upward until -1. */ | 437 | their range is counted upward until -1. */ |
393 | fat_bpb.bpb_rootclus = 0 - dirclusters; /* backwards, before the data */ | 438 | fat_bpb->bpb_rootclus = 0 - dirclusters; /* backwards, before the data */ |
394 | } | 439 | } |
395 | else | 440 | else |
396 | #endif /* #ifdef HAVE_FAT16SUPPORT */ | 441 | #endif /* #ifdef HAVE_FAT16SUPPORT */ |
397 | { /* FAT32 specific part of BPB */ | 442 | { /* FAT32 specific part of BPB */ |
398 | fat_bpb.bpb_rootclus = BYTES2INT32(buf,BPB_ROOTCLUS); | 443 | fat_bpb->bpb_rootclus = BYTES2INT32(buf,BPB_ROOTCLUS); |
399 | fat_bpb.bpb_fsinfo = BYTES2INT16(buf,BPB_FSINFO); | 444 | fat_bpb->bpb_fsinfo = BYTES2INT16(buf,BPB_FSINFO); |
400 | fat_bpb.rootdirsector = cluster2sec(fat_bpb.bpb_rootclus); | 445 | fat_bpb->rootdirsector = cluster2sec(IF_MV2(fat_bpb,) fat_bpb->bpb_rootclus); |
401 | } | 446 | } |
402 | 447 | ||
403 | rc = bpb_is_sane(); | 448 | rc = bpb_is_sane(IF_MV(fat_bpb)); |
404 | if (rc < 0) | 449 | if (rc < 0) |
405 | { | 450 | { |
406 | DEBUGF( "fat_mount() - BPB is not sane\n"); | 451 | DEBUGF( "fat_mount() - BPB is not sane\n"); |
@@ -408,59 +453,68 @@ int fat_mount(int startsector) | |||
408 | } | 453 | } |
409 | 454 | ||
410 | #ifdef HAVE_FAT16SUPPORT | 455 | #ifdef HAVE_FAT16SUPPORT |
411 | if (fat_bpb.is_fat16) | 456 | if (fat_bpb->is_fat16) |
412 | { | 457 | { |
413 | fat_bpb.fsinfo.freecount = 0xffffffff; /* force recalc below */ | 458 | fat_bpb->fsinfo.freecount = 0xffffffff; /* force recalc below */ |
414 | fat_bpb.fsinfo.nextfree = 0xffffffff; | 459 | fat_bpb->fsinfo.nextfree = 0xffffffff; |
415 | } | 460 | } |
416 | else | 461 | else |
417 | #endif /* #ifdef HAVE_FAT16SUPPORT */ | 462 | #endif /* #ifdef HAVE_FAT16SUPPORT */ |
418 | { | 463 | { |
419 | /* Read the fsinfo sector */ | 464 | /* Read the fsinfo sector */ |
420 | rc = ata_read_sectors(startsector + fat_bpb.bpb_fsinfo, 1, buf); | 465 | rc = ata_read_sectors(IF_MV2(drive,) |
466 | startsector + fat_bpb->bpb_fsinfo, 1, buf); | ||
421 | if (rc < 0) | 467 | if (rc < 0) |
422 | { | 468 | { |
423 | DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc); | 469 | DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc); |
424 | return rc * 10 - 4; | 470 | return rc * 10 - 4; |
425 | } | 471 | } |
426 | fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); | 472 | fat_bpb->fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); |
427 | fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); | 473 | fat_bpb->fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); |
428 | } | 474 | } |
429 | 475 | ||
430 | /* calculate freecount if unset */ | 476 | /* calculate freecount if unset */ |
431 | if ( fat_bpb.fsinfo.freecount == 0xffffffff ) | 477 | if ( fat_bpb->fsinfo.freecount == 0xffffffff ) |
432 | { | 478 | { |
433 | fat_recalc_free(); | 479 | fat_recalc_free(IF_MV(volume)); |
434 | } | 480 | } |
435 | 481 | ||
436 | LDEBUGF("Freecount: %d\n",fat_bpb.fsinfo.freecount); | 482 | LDEBUGF("Freecount: %d\n",fat_bpb->fsinfo.freecount); |
437 | LDEBUGF("Nextfree: 0x%x\n",fat_bpb.fsinfo.nextfree); | 483 | LDEBUGF("Nextfree: 0x%x\n",fat_bpb->fsinfo.nextfree); |
438 | LDEBUGF("Cluster count: 0x%x\n",fat_bpb.dataclusters); | 484 | LDEBUGF("Cluster count: 0x%x\n",fat_bpb->dataclusters); |
439 | LDEBUGF("Sectors per cluster: %d\n",fat_bpb.bpb_secperclus); | 485 | LDEBUGF("Sectors per cluster: %d\n",fat_bpb->bpb_secperclus); |
440 | LDEBUGF("FAT sectors: 0x%x\n",fat_bpb.fatsize); | 486 | LDEBUGF("FAT sectors: 0x%x\n",fat_bpb->fatsize); |
487 | |||
488 | #ifdef HAVE_MULTIVOLUME | ||
489 | fat_bpb->mounted = true; | ||
490 | #endif | ||
441 | 491 | ||
442 | return 0; | 492 | return 0; |
443 | } | 493 | } |
444 | 494 | ||
445 | void fat_recalc_free(void) | 495 | void fat_recalc_free(IF_MV_NONVOID(int volume)) |
446 | { | 496 | { |
497 | #ifndef HAVE_MULTIVOLUME | ||
498 | const int volume = 0; | ||
499 | #endif | ||
500 | struct bpb* fat_bpb = &fat_bpbs[volume]; | ||
447 | int free = 0; | 501 | int free = 0; |
448 | unsigned i; | 502 | unsigned i; |
449 | #ifdef HAVE_FAT16SUPPORT | 503 | #ifdef HAVE_FAT16SUPPORT |
450 | if (fat_bpb.is_fat16) | 504 | if (fat_bpb->is_fat16) |
451 | { | 505 | { |
452 | for (i = 0; i<fat_bpb.fatsize; i++) { | 506 | for (i = 0; i<fat_bpb->fatsize; i++) { |
453 | unsigned int j; | 507 | unsigned int j; |
454 | unsigned short* fat = cache_fat_sector(i); | 508 | unsigned short* fat = cache_fat_sector(IF_MV2(fat_bpb,) i); |
455 | for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) { | 509 | for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) { |
456 | unsigned int c = i * CLUSTERS_PER_FAT16_SECTOR + j; | 510 | unsigned int c = i * CLUSTERS_PER_FAT16_SECTOR + j; |
457 | if ( c > fat_bpb.dataclusters+1 ) /* nr 0 is unused */ | 511 | if ( c > fat_bpb->dataclusters+1 ) /* nr 0 is unused */ |
458 | break; | 512 | break; |
459 | 513 | ||
460 | if (SWAB16(fat[j]) == 0x0000) { | 514 | if (SWAB16(fat[j]) == 0x0000) { |
461 | free++; | 515 | free++; |
462 | if ( fat_bpb.fsinfo.nextfree == 0xffffffff ) | 516 | if ( fat_bpb->fsinfo.nextfree == 0xffffffff ) |
463 | fat_bpb.fsinfo.nextfree = c; | 517 | fat_bpb->fsinfo.nextfree = c; |
464 | } | 518 | } |
465 | } | 519 | } |
466 | } | 520 | } |
@@ -468,116 +522,153 @@ void fat_recalc_free(void) | |||
468 | else | 522 | else |
469 | #endif /* #ifdef HAVE_FAT16SUPPORT */ | 523 | #endif /* #ifdef HAVE_FAT16SUPPORT */ |
470 | { | 524 | { |
471 | for (i = 0; i<fat_bpb.fatsize; i++) { | 525 | for (i = 0; i<fat_bpb->fatsize; i++) { |
472 | unsigned int j; | 526 | unsigned int j; |
473 | unsigned int* fat = cache_fat_sector(i); | 527 | unsigned int* fat = cache_fat_sector(IF_MV2(fat_bpb,) i); |
474 | for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { | 528 | for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { |
475 | unsigned int c = i * CLUSTERS_PER_FAT_SECTOR + j; | 529 | unsigned int c = i * CLUSTERS_PER_FAT_SECTOR + j; |
476 | if ( c > fat_bpb.dataclusters+1 ) /* nr 0 is unused */ | 530 | if ( c > fat_bpb->dataclusters+1 ) /* nr 0 is unused */ |
477 | break; | 531 | break; |
478 | 532 | ||
479 | if (!(SWAB32(fat[j]) & 0x0fffffff)) { | 533 | if (!(SWAB32(fat[j]) & 0x0fffffff)) { |
480 | free++; | 534 | free++; |
481 | if ( fat_bpb.fsinfo.nextfree == 0xffffffff ) | 535 | if ( fat_bpb->fsinfo.nextfree == 0xffffffff ) |
482 | fat_bpb.fsinfo.nextfree = c; | 536 | fat_bpb->fsinfo.nextfree = c; |
483 | } | 537 | } |
484 | } | 538 | } |
485 | } | 539 | } |
486 | } | 540 | } |
487 | fat_bpb.fsinfo.freecount = free; | 541 | fat_bpb->fsinfo.freecount = free; |
488 | update_fsinfo(); | 542 | update_fsinfo(IF_MV(fat_bpb)); |
489 | } | 543 | } |
490 | 544 | ||
491 | static int bpb_is_sane(void) | 545 | static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb)) |
492 | { | 546 | { |
493 | if(fat_bpb.bpb_bytspersec != 512) | 547 | #ifndef HAVE_MULTIVOLUME |
548 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
549 | #endif | ||
550 | if(fat_bpb->bpb_bytspersec != 512) | ||
494 | { | 551 | { |
495 | DEBUGF( "bpb_is_sane() - Error: sector size is not 512 (%d)\n", | 552 | DEBUGF( "bpb_is_sane() - Error: sector size is not 512 (%d)\n", |
496 | fat_bpb.bpb_bytspersec); | 553 | fat_bpb->bpb_bytspersec); |
497 | return -1; | 554 | return -1; |
498 | } | 555 | } |
499 | if(fat_bpb.bpb_secperclus * fat_bpb.bpb_bytspersec > 128*1024) | 556 | if(fat_bpb->bpb_secperclus * fat_bpb->bpb_bytspersec > 128*1024) |
500 | { | 557 | { |
501 | DEBUGF( "bpb_is_sane() - Error: cluster size is larger than 128K " | 558 | DEBUGF( "bpb_is_sane() - Error: cluster size is larger than 128K " |
502 | "(%d * %d = %d)\n", | 559 | "(%d * %d = %d)\n", |
503 | fat_bpb.bpb_bytspersec, fat_bpb.bpb_secperclus, | 560 | fat_bpb->bpb_bytspersec, fat_bpb->bpb_secperclus, |
504 | fat_bpb.bpb_bytspersec * fat_bpb.bpb_secperclus); | 561 | fat_bpb->bpb_bytspersec * fat_bpb->bpb_secperclus); |
505 | return -2; | 562 | return -2; |
506 | } | 563 | } |
507 | if(fat_bpb.bpb_numfats != 2) | 564 | if(fat_bpb->bpb_numfats != 2) |
508 | { | 565 | { |
509 | DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n", | 566 | DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n", |
510 | fat_bpb.bpb_numfats); | 567 | fat_bpb->bpb_numfats); |
511 | } | 568 | } |
512 | if(fat_bpb.bpb_media != 0xf0 && fat_bpb.bpb_media < 0xf8) | 569 | if(fat_bpb->bpb_media != 0xf0 && fat_bpb->bpb_media < 0xf8) |
513 | { | 570 | { |
514 | DEBUGF( "bpb_is_sane() - Warning: Non-standard " | 571 | DEBUGF( "bpb_is_sane() - Warning: Non-standard " |
515 | "media type (0x%02x)\n", | 572 | "media type (0x%02x)\n", |
516 | fat_bpb.bpb_media); | 573 | fat_bpb->bpb_media); |
517 | } | 574 | } |
518 | if(fat_bpb.last_word != 0xaa55) | 575 | if(fat_bpb->last_word != 0xaa55) |
519 | { | 576 | { |
520 | DEBUGF( "bpb_is_sane() - Error: Last word is not " | 577 | DEBUGF( "bpb_is_sane() - Error: Last word is not " |
521 | "0xaa55 (0x%04x)\n", fat_bpb.last_word); | 578 | "0xaa55 (0x%04x)\n", fat_bpb->last_word); |
522 | return -3; | 579 | return -3; |
523 | } | 580 | } |
524 | 581 | ||
525 | if (fat_bpb.fsinfo.freecount > | 582 | if (fat_bpb->fsinfo.freecount > |
526 | (fat_bpb.totalsectors - fat_bpb.firstdatasector)/ | 583 | (fat_bpb->totalsectors - fat_bpb->firstdatasector)/ |
527 | fat_bpb.bpb_secperclus) | 584 | fat_bpb->bpb_secperclus) |
528 | { | 585 | { |
529 | DEBUGF( "bpb_is_sane() - Error: FSInfo.Freecount > disk size " | 586 | DEBUGF( "bpb_is_sane() - Error: FSInfo.Freecount > disk size " |
530 | "(0x%04x)\n", fat_bpb.fsinfo.freecount); | 587 | "(0x%04x)\n", fat_bpb->fsinfo.freecount); |
531 | return -4; | 588 | return -4; |
532 | } | 589 | } |
533 | 590 | ||
534 | return 0; | 591 | return 0; |
535 | } | 592 | } |
536 | 593 | ||
537 | static void *cache_fat_sector(int fatsector) | 594 | static void flush_fat_sector(struct fat_cache_entry *fce, |
595 | unsigned char *sectorbuf) | ||
538 | { | 596 | { |
539 | int secnum = fatsector + fat_bpb.bpb_rsvdseccnt; | 597 | int rc; |
598 | int secnum; | ||
599 | |||
600 | /* With multivolume, use only the FAT info from the cached sector! */ | ||
601 | #ifdef HAVE_MULTIVOLUME | ||
602 | secnum = fce->secnum + fce->fat_vol->startsector; | ||
603 | #else | ||
604 | secnum = fce->secnum + fat_bpbs[0].startsector; | ||
605 | #endif | ||
606 | |||
607 | /* Write to the first FAT */ | ||
608 | rc = ata_write_sectors(IF_MV2(fce->fat_vol->drive,) | ||
609 | secnum, 1, | ||
610 | sectorbuf); | ||
611 | if(rc < 0) | ||
612 | { | ||
613 | panicf("cache_fat_sector() - Could not write sector %d" | ||
614 | " (error %d)\n", | ||
615 | secnum, rc); | ||
616 | } | ||
617 | #ifdef HAVE_MULTIVOLUME | ||
618 | if(fce->fat_vol->bpb_numfats > 1) | ||
619 | #else | ||
620 | if(fat_bpbs[0].bpb_numfats > 1) | ||
621 | #endif | ||
622 | { | ||
623 | /* Write to the second FAT */ | ||
624 | #ifdef HAVE_MULTIVOLUME | ||
625 | secnum += fce->fat_vol->fatsize; | ||
626 | #else | ||
627 | secnum += fat_bpbs[0].fatsize; | ||
628 | #endif | ||
629 | rc = ata_write_sectors(IF_MV2(fce->fat_vol->drive,) | ||
630 | secnum, 1, sectorbuf); | ||
631 | if(rc < 0) | ||
632 | { | ||
633 | panicf("cache_fat_sector() - Could not write sector %d" | ||
634 | " (error %d)\n", | ||
635 | secnum, rc); | ||
636 | } | ||
637 | } | ||
638 | fce->dirty = false; | ||
639 | } | ||
640 | |||
641 | static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int fatsector) | ||
642 | { | ||
643 | #ifndef HAVE_MULTIVOLUME | ||
644 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
645 | #endif | ||
646 | int secnum = fatsector + fat_bpb->bpb_rsvdseccnt; | ||
540 | int cache_index = secnum & FAT_CACHE_MASK; | 647 | int cache_index = secnum & FAT_CACHE_MASK; |
541 | struct fat_cache_entry *fce = &fat_cache[cache_index]; | 648 | struct fat_cache_entry *fce = &fat_cache[cache_index]; |
542 | unsigned char *sectorbuf = &fat_cache_sectors[cache_index][0]; | 649 | unsigned char *sectorbuf = &fat_cache_sectors[cache_index][0]; |
543 | int rc; | 650 | int rc; |
544 | 651 | ||
545 | /* Delete the cache entry if it isn't the sector we want */ | 652 | /* Delete the cache entry if it isn't the sector we want */ |
546 | if(fce->inuse && fce->secnum != secnum) | 653 | if(fce->inuse && (fce->secnum != secnum |
654 | #ifdef HAVE_MULTIVOLUME | ||
655 | || fce->fat_vol != fat_bpb | ||
656 | #endif | ||
657 | )) | ||
547 | { | 658 | { |
548 | /* Write back if it is dirty */ | 659 | /* Write back if it is dirty */ |
549 | if(fce->dirty) | 660 | if(fce->dirty) |
550 | { | 661 | { |
551 | rc = ata_write_sectors(fce->secnum+fat_bpb.startsector, 1, | 662 | flush_fat_sector(fce, sectorbuf); |
552 | sectorbuf); | ||
553 | if(rc < 0) | ||
554 | { | ||
555 | panicf("cache_fat_sector() - Could not write sector %d" | ||
556 | " (error %d)\n", | ||
557 | secnum, rc); | ||
558 | } | ||
559 | if(fat_bpb.bpb_numfats > 1) | ||
560 | { | ||
561 | /* Write to the second FAT */ | ||
562 | rc = ata_write_sectors(fce->secnum+fat_bpb.startsector+ | ||
563 | fat_bpb.fatsize, 1, sectorbuf); | ||
564 | if(rc < 0) | ||
565 | { | ||
566 | panicf("cache_fat_sector() - Could not write sector %d" | ||
567 | " (error %d)\n", | ||
568 | secnum + fat_bpb.fatsize, rc); | ||
569 | } | ||
570 | } | ||
571 | } | 663 | } |
572 | fce->secnum = 8; /* Normally an unused sector */ | ||
573 | fce->dirty = false; | ||
574 | fce->inuse = false; | 664 | fce->inuse = false; |
575 | } | 665 | } |
576 | 666 | ||
577 | /* Load the sector if it is not cached */ | 667 | /* Load the sector if it is not cached */ |
578 | if(!fce->inuse) | 668 | if(!fce->inuse) |
579 | { | 669 | { |
580 | rc = ata_read_sectors(secnum + fat_bpb.startsector,1, | 670 | rc = ata_read_sectors(IF_MV2(fat_bpb->drive,) |
671 | secnum + fat_bpb->startsector,1, | ||
581 | sectorbuf); | 672 | sectorbuf); |
582 | if(rc < 0) | 673 | if(rc < 0) |
583 | { | 674 | { |
@@ -587,26 +678,32 @@ static void *cache_fat_sector(int fatsector) | |||
587 | } | 678 | } |
588 | fce->inuse = true; | 679 | fce->inuse = true; |
589 | fce->secnum = secnum; | 680 | fce->secnum = secnum; |
681 | #ifdef HAVE_MULTIVOLUME | ||
682 | fce->fat_vol = fat_bpb; | ||
683 | #endif | ||
590 | } | 684 | } |
591 | return sectorbuf; | 685 | return sectorbuf; |
592 | } | 686 | } |
593 | 687 | ||
594 | static unsigned int find_free_cluster(unsigned int startcluster) | 688 | static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int startcluster) |
595 | { | 689 | { |
690 | #ifndef HAVE_MULTIVOLUME | ||
691 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
692 | #endif | ||
596 | unsigned int sector; | 693 | unsigned int sector; |
597 | unsigned int offset; | 694 | unsigned int offset; |
598 | unsigned int i; | 695 | unsigned int i; |
599 | 696 | ||
600 | #ifdef HAVE_FAT16SUPPORT | 697 | #ifdef HAVE_FAT16SUPPORT |
601 | if (fat_bpb.is_fat16) | 698 | if (fat_bpb->is_fat16) |
602 | { | 699 | { |
603 | sector = startcluster / CLUSTERS_PER_FAT16_SECTOR; | 700 | sector = startcluster / CLUSTERS_PER_FAT16_SECTOR; |
604 | offset = startcluster % CLUSTERS_PER_FAT16_SECTOR; | 701 | offset = startcluster % CLUSTERS_PER_FAT16_SECTOR; |
605 | 702 | ||
606 | for (i = 0; i<fat_bpb.fatsize; i++) { | 703 | for (i = 0; i<fat_bpb->fatsize; i++) { |
607 | unsigned int j; | 704 | unsigned int j; |
608 | unsigned int nr = (i + sector) % fat_bpb.fatsize; | 705 | unsigned int nr = (i + sector) % fat_bpb->fatsize; |
609 | unsigned short* fat = cache_fat_sector(nr); | 706 | unsigned short* fat = cache_fat_sector(IF_MV2(fat_bpb,) nr); |
610 | if ( !fat ) | 707 | if ( !fat ) |
611 | break; | 708 | break; |
612 | for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) { | 709 | for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) { |
@@ -615,10 +712,10 @@ static unsigned int find_free_cluster(unsigned int startcluster) | |||
615 | unsigned int c = nr * CLUSTERS_PER_FAT16_SECTOR + k; | 712 | unsigned int c = nr * CLUSTERS_PER_FAT16_SECTOR + k; |
616 | /* Ignore the reserved clusters 0 & 1, and also | 713 | /* Ignore the reserved clusters 0 & 1, and also |
617 | cluster numbers out of bounds */ | 714 | cluster numbers out of bounds */ |
618 | if ( c < 2 || c > fat_bpb.dataclusters+1 ) | 715 | if ( c < 2 || c > fat_bpb->dataclusters+1 ) |
619 | continue; | 716 | continue; |
620 | LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); | 717 | LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); |
621 | fat_bpb.fsinfo.nextfree = c; | 718 | fat_bpb->fsinfo.nextfree = c; |
622 | return c; | 719 | return c; |
623 | } | 720 | } |
624 | } | 721 | } |
@@ -631,10 +728,10 @@ static unsigned int find_free_cluster(unsigned int startcluster) | |||
631 | sector = startcluster / CLUSTERS_PER_FAT_SECTOR; | 728 | sector = startcluster / CLUSTERS_PER_FAT_SECTOR; |
632 | offset = startcluster % CLUSTERS_PER_FAT_SECTOR; | 729 | offset = startcluster % CLUSTERS_PER_FAT_SECTOR; |
633 | 730 | ||
634 | for (i = 0; i<fat_bpb.fatsize; i++) { | 731 | for (i = 0; i<fat_bpb->fatsize; i++) { |
635 | unsigned int j; | 732 | unsigned int j; |
636 | unsigned int nr = (i + sector) % fat_bpb.fatsize; | 733 | unsigned int nr = (i + sector) % fat_bpb->fatsize; |
637 | unsigned int* fat = cache_fat_sector(nr); | 734 | unsigned int* fat = cache_fat_sector(IF_MV2(fat_bpb,) nr); |
638 | if ( !fat ) | 735 | if ( !fat ) |
639 | break; | 736 | break; |
640 | for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { | 737 | for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) { |
@@ -643,10 +740,10 @@ static unsigned int find_free_cluster(unsigned int startcluster) | |||
643 | unsigned int c = nr * CLUSTERS_PER_FAT_SECTOR + k; | 740 | unsigned int c = nr * CLUSTERS_PER_FAT_SECTOR + k; |
644 | /* Ignore the reserved clusters 0 & 1, and also | 741 | /* Ignore the reserved clusters 0 & 1, and also |
645 | cluster numbers out of bounds */ | 742 | cluster numbers out of bounds */ |
646 | if ( c < 2 || c > fat_bpb.dataclusters+1 ) | 743 | if ( c < 2 || c > fat_bpb->dataclusters+1 ) |
647 | continue; | 744 | continue; |
648 | LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); | 745 | LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); |
649 | fat_bpb.fsinfo.nextfree = c; | 746 | fat_bpb->fsinfo.nextfree = c; |
650 | return c; | 747 | return c; |
651 | } | 748 | } |
652 | } | 749 | } |
@@ -658,10 +755,13 @@ static unsigned int find_free_cluster(unsigned int startcluster) | |||
658 | return 0; /* 0 is an illegal cluster number */ | 755 | return 0; /* 0 is an illegal cluster number */ |
659 | } | 756 | } |
660 | 757 | ||
661 | static int update_fat_entry(unsigned int entry, unsigned int val) | 758 | static int update_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned int entry, unsigned int val) |
662 | { | 759 | { |
760 | #ifndef HAVE_MULTIVOLUME | ||
761 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
762 | #endif | ||
663 | #ifdef HAVE_FAT16SUPPORT | 763 | #ifdef HAVE_FAT16SUPPORT |
664 | if (fat_bpb.is_fat16) | 764 | if (fat_bpb->is_fat16) |
665 | { | 765 | { |
666 | int sector = entry / CLUSTERS_PER_FAT16_SECTOR; | 766 | int sector = entry / CLUSTERS_PER_FAT16_SECTOR; |
667 | int offset = entry % CLUSTERS_PER_FAT16_SECTOR; | 767 | int offset = entry % CLUSTERS_PER_FAT16_SECTOR; |
@@ -677,24 +777,24 @@ static int update_fat_entry(unsigned int entry, unsigned int val) | |||
677 | if ( entry < 2 ) | 777 | if ( entry < 2 ) |
678 | panicf("Updating reserved FAT entry %d.\n",entry); | 778 | panicf("Updating reserved FAT entry %d.\n",entry); |
679 | 779 | ||
680 | sec = cache_fat_sector(sector); | 780 | sec = cache_fat_sector(IF_MV2(fat_bpb,) sector); |
681 | if (!sec) | 781 | if (!sec) |
682 | { | 782 | { |
683 | DEBUGF( "update_entry() - Could not cache sector %d\n", sector); | 783 | DEBUGF( "update_entry() - Could not cache sector %d\n", sector); |
684 | return -1; | 784 | return -1; |
685 | } | 785 | } |
686 | fat_cache[(sector + fat_bpb.bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; | 786 | fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; |
687 | 787 | ||
688 | if ( val ) { | 788 | if ( val ) { |
689 | if (SWAB16(sec[offset]) == 0x0000 && fat_bpb.fsinfo.freecount > 0) | 789 | if (SWAB16(sec[offset]) == 0x0000 && fat_bpb->fsinfo.freecount > 0) |
690 | fat_bpb.fsinfo.freecount--; | 790 | fat_bpb->fsinfo.freecount--; |
691 | } | 791 | } |
692 | else { | 792 | else { |
693 | if (SWAB16(sec[offset])) | 793 | if (SWAB16(sec[offset])) |
694 | fat_bpb.fsinfo.freecount++; | 794 | fat_bpb->fsinfo.freecount++; |
695 | } | 795 | } |
696 | 796 | ||
697 | LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb.fsinfo.freecount); | 797 | LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb->fsinfo.freecount); |
698 | 798 | ||
699 | sec[offset] = SWAB16(val); | 799 | sec[offset] = SWAB16(val); |
700 | } | 800 | } |
@@ -713,25 +813,25 @@ static int update_fat_entry(unsigned int entry, unsigned int val) | |||
713 | if ( entry < 2 ) | 813 | if ( entry < 2 ) |
714 | panicf("Updating reserved FAT entry %d.\n",entry); | 814 | panicf("Updating reserved FAT entry %d.\n",entry); |
715 | 815 | ||
716 | sec = cache_fat_sector(sector); | 816 | sec = cache_fat_sector(IF_MV2(fat_bpb,) sector); |
717 | if (!sec) | 817 | if (!sec) |
718 | { | 818 | { |
719 | DEBUGF( "update_entry() - Could not cache sector %d\n", sector); | 819 | DEBUGF( "update_entry() - Could not cache sector %d\n", sector); |
720 | return -1; | 820 | return -1; |
721 | } | 821 | } |
722 | fat_cache[(sector + fat_bpb.bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; | 822 | fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; |
723 | 823 | ||
724 | if ( val ) { | 824 | if ( val ) { |
725 | if (!(SWAB32(sec[offset]) & 0x0fffffff) && | 825 | if (!(SWAB32(sec[offset]) & 0x0fffffff) && |
726 | fat_bpb.fsinfo.freecount > 0) | 826 | fat_bpb->fsinfo.freecount > 0) |
727 | fat_bpb.fsinfo.freecount--; | 827 | fat_bpb->fsinfo.freecount--; |
728 | } | 828 | } |
729 | else { | 829 | else { |
730 | if (SWAB32(sec[offset]) & 0x0fffffff) | 830 | if (SWAB32(sec[offset]) & 0x0fffffff) |
731 | fat_bpb.fsinfo.freecount++; | 831 | fat_bpb->fsinfo.freecount++; |
732 | } | 832 | } |
733 | 833 | ||
734 | LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb.fsinfo.freecount); | 834 | LDEBUGF("update_fat_entry: %d free clusters\n", fat_bpb->fsinfo.freecount); |
735 | 835 | ||
736 | /* don't change top 4 bits */ | 836 | /* don't change top 4 bits */ |
737 | sec[offset] &= SWAB32(0xf0000000); | 837 | sec[offset] &= SWAB32(0xf0000000); |
@@ -741,16 +841,19 @@ static int update_fat_entry(unsigned int entry, unsigned int val) | |||
741 | return 0; | 841 | return 0; |
742 | } | 842 | } |
743 | 843 | ||
744 | static int read_fat_entry(unsigned int entry) | 844 | static int read_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned int entry) |
745 | { | 845 | { |
846 | #ifndef HAVE_MULTIVOLUME | ||
847 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
848 | #endif | ||
746 | #ifdef HAVE_FAT16SUPPORT | 849 | #ifdef HAVE_FAT16SUPPORT |
747 | if (fat_bpb.is_fat16) | 850 | if (fat_bpb->is_fat16) |
748 | { | 851 | { |
749 | int sector = entry / CLUSTERS_PER_FAT16_SECTOR; | 852 | int sector = entry / CLUSTERS_PER_FAT16_SECTOR; |
750 | int offset = entry % CLUSTERS_PER_FAT16_SECTOR; | 853 | int offset = entry % CLUSTERS_PER_FAT16_SECTOR; |
751 | unsigned short* sec; | 854 | unsigned short* sec; |
752 | 855 | ||
753 | sec = cache_fat_sector(sector); | 856 | sec = cache_fat_sector(IF_MV2(fat_bpb,) sector); |
754 | if (!sec) | 857 | if (!sec) |
755 | { | 858 | { |
756 | DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); | 859 | DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); |
@@ -766,7 +869,7 @@ static int read_fat_entry(unsigned int entry) | |||
766 | int offset = entry % CLUSTERS_PER_FAT_SECTOR; | 869 | int offset = entry % CLUSTERS_PER_FAT_SECTOR; |
767 | unsigned int* sec; | 870 | unsigned int* sec; |
768 | 871 | ||
769 | sec = cache_fat_sector(sector); | 872 | sec = cache_fat_sector(IF_MV2(fat_bpb,) sector); |
770 | if (!sec) | 873 | if (!sec) |
771 | { | 874 | { |
772 | DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); | 875 | DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); |
@@ -777,20 +880,23 @@ static int read_fat_entry(unsigned int entry) | |||
777 | } | 880 | } |
778 | } | 881 | } |
779 | 882 | ||
780 | static int get_next_cluster(int cluster) | 883 | static int get_next_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster) |
781 | { | 884 | { |
885 | #ifndef HAVE_MULTIVOLUME | ||
886 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
887 | #endif | ||
782 | int next_cluster; | 888 | int next_cluster; |
783 | int eof_mark = FAT_EOF_MARK; | 889 | int eof_mark = FAT_EOF_MARK; |
784 | 890 | ||
785 | #ifdef HAVE_FAT16SUPPORT | 891 | #ifdef HAVE_FAT16SUPPORT |
786 | if (fat_bpb.is_fat16) | 892 | if (fat_bpb->is_fat16) |
787 | { | 893 | { |
788 | eof_mark &= 0xFFFF; /* only 16 bit */ | 894 | eof_mark &= 0xFFFF; /* only 16 bit */ |
789 | if (cluster < 0) /* FAT16 root dir */ | 895 | if (cluster < 0) /* FAT16 root dir */ |
790 | return cluster + 1; /* don't use the FAT */ | 896 | return cluster + 1; /* don't use the FAT */ |
791 | } | 897 | } |
792 | #endif | 898 | #endif |
793 | next_cluster = read_fat_entry(cluster); | 899 | next_cluster = read_fat_entry(IF_MV2(fat_bpb,) cluster); |
794 | 900 | ||
795 | /* is this last cluster in chain? */ | 901 | /* is this last cluster in chain? */ |
796 | if ( next_cluster >= eof_mark ) | 902 | if ( next_cluster >= eof_mark ) |
@@ -799,31 +905,36 @@ static int get_next_cluster(int cluster) | |||
799 | return next_cluster; | 905 | return next_cluster; |
800 | } | 906 | } |
801 | 907 | ||
802 | static int update_fsinfo(void) | 908 | static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)) |
803 | { | 909 | { |
910 | #ifndef HAVE_MULTIVOLUME | ||
911 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
912 | #endif | ||
804 | unsigned char fsinfo[SECTOR_SIZE]; | 913 | unsigned char fsinfo[SECTOR_SIZE]; |
805 | unsigned int* intptr; | 914 | unsigned int* intptr; |
806 | int rc; | 915 | int rc; |
807 | 916 | ||
808 | #ifdef HAVE_FAT16SUPPORT | 917 | #ifdef HAVE_FAT16SUPPORT |
809 | if (fat_bpb.is_fat16) | 918 | if (fat_bpb->is_fat16) |
810 | return 0; /* FAT16 has no FsInfo */ | 919 | return 0; /* FAT16 has no FsInfo */ |
811 | #endif /* #ifdef HAVE_FAT16SUPPORT */ | 920 | #endif /* #ifdef HAVE_FAT16SUPPORT */ |
812 | 921 | ||
813 | /* update fsinfo */ | 922 | /* update fsinfo */ |
814 | rc = ata_read_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo, 1,fsinfo); | 923 | rc = ata_read_sectors(IF_MV2(fat_bpb->drive,) |
924 | fat_bpb->startsector + fat_bpb->bpb_fsinfo, 1,fsinfo); | ||
815 | if (rc < 0) | 925 | if (rc < 0) |
816 | { | 926 | { |
817 | DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", rc); | 927 | DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", rc); |
818 | return rc * 10 - 1; | 928 | return rc * 10 - 1; |
819 | } | 929 | } |
820 | intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]); | 930 | intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]); |
821 | *intptr = SWAB32(fat_bpb.fsinfo.freecount); | 931 | *intptr = SWAB32(fat_bpb->fsinfo.freecount); |
822 | 932 | ||
823 | intptr = (int*)&(fsinfo[FSINFO_NEXTFREE]); | 933 | intptr = (int*)&(fsinfo[FSINFO_NEXTFREE]); |
824 | *intptr = SWAB32(fat_bpb.fsinfo.nextfree); | 934 | *intptr = SWAB32(fat_bpb->fsinfo.nextfree); |
825 | 935 | ||
826 | rc = ata_write_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo,1,fsinfo); | 936 | rc = ata_write_sectors(IF_MV2(fat_bpb->drive,) |
937 | fat_bpb->startsector + fat_bpb->bpb_fsinfo,1,fsinfo); | ||
827 | if (rc < 0) | 938 | if (rc < 0) |
828 | { | 939 | { |
829 | DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", rc); | 940 | DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", rc); |
@@ -833,48 +944,24 @@ static int update_fsinfo(void) | |||
833 | return 0; | 944 | return 0; |
834 | } | 945 | } |
835 | 946 | ||
836 | static int flush_fat(void) | 947 | static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb)) |
837 | { | 948 | { |
838 | int i; | 949 | int i; |
839 | int rc; | 950 | int rc; |
840 | unsigned char *sec; | 951 | unsigned char *sec; |
841 | int secnum; | ||
842 | LDEBUGF("flush_fat()\n"); | 952 | LDEBUGF("flush_fat()\n"); |
843 | 953 | ||
844 | for(i = 0;i < FAT_CACHE_SIZE;i++) | 954 | for(i = 0;i < FAT_CACHE_SIZE;i++) |
845 | { | 955 | { |
846 | if(fat_cache[i].inuse && fat_cache[i].dirty) | 956 | struct fat_cache_entry *fce = &fat_cache[i]; |
957 | if(fce->inuse && fce->dirty) | ||
847 | { | 958 | { |
848 | secnum = fat_cache[i].secnum + fat_bpb.startsector; | ||
849 | LDEBUGF("Flushing FAT sector %x\n", secnum); | ||
850 | sec = fat_cache_sectors[i]; | 959 | sec = fat_cache_sectors[i]; |
851 | 960 | flush_fat_sector(fce, sec); | |
852 | /* Write to the first FAT */ | ||
853 | rc = ata_write_sectors(secnum, 1, sec); | ||
854 | if(rc) | ||
855 | { | ||
856 | DEBUGF( "flush_fat() - Couldn't write" | ||
857 | " sector %d (error %d)\n", secnum, rc); | ||
858 | return rc * 10 - 1; | ||
859 | } | ||
860 | |||
861 | if(fat_bpb.bpb_numfats > 1 ) | ||
862 | { | ||
863 | /* Write to the second FAT */ | ||
864 | rc = ata_write_sectors(secnum + fat_bpb.fatsize, 1, sec); | ||
865 | if (rc) | ||
866 | { | ||
867 | DEBUGF( "flush_fat() - Couldn't write" | ||
868 | " sector %d (error %d)\n", | ||
869 | secnum + fat_bpb.fatsize, rc); | ||
870 | return rc * 10 - 2; | ||
871 | } | ||
872 | } | ||
873 | fat_cache[i].dirty = false; | ||
874 | } | 961 | } |
875 | } | 962 | } |
876 | 963 | ||
877 | rc = update_fsinfo(); | 964 | rc = update_fsinfo(IF_MV(fat_bpb)); |
878 | if (rc < 0) | 965 | if (rc < 0) |
879 | return rc * 10 - 3; | 966 | return rc * 10 - 3; |
880 | 967 | ||
@@ -1108,6 +1195,11 @@ static int add_dir_entry(struct fat_dir* dir, | |||
1108 | bool is_directory, | 1195 | bool is_directory, |
1109 | bool dotdir) | 1196 | bool dotdir) |
1110 | { | 1197 | { |
1198 | #ifdef HAVE_MULTIVOLUME | ||
1199 | struct bpb* fat_bpb = &fat_bpbs[dir->file.volume]; | ||
1200 | #else | ||
1201 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
1202 | #endif | ||
1111 | unsigned char buf[SECTOR_SIZE]; | 1203 | unsigned char buf[SECTOR_SIZE]; |
1112 | unsigned char shortname[16]; | 1204 | unsigned char shortname[16]; |
1113 | int rc; | 1205 | int rc; |
@@ -1122,6 +1214,10 @@ static int add_dir_entry(struct fat_dir* dir, | |||
1122 | LDEBUGF( "add_dir_entry(%s,%x)\n", | 1214 | LDEBUGF( "add_dir_entry(%s,%x)\n", |
1123 | name, file->firstcluster); | 1215 | name, file->firstcluster); |
1124 | 1216 | ||
1217 | #ifdef HAVE_MULTIVOLUME | ||
1218 | file->volume = dir->file.volume; /* inherit the volume, to make sure */ | ||
1219 | #endif | ||
1220 | |||
1125 | /* The "." and ".." directory entries must not be long names */ | 1221 | /* The "." and ".." directory entries must not be long names */ |
1126 | if(dotdir) { | 1222 | if(dotdir) { |
1127 | int i; | 1223 | int i; |
@@ -1173,7 +1269,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
1173 | rc = fat_readwrite(&dir->file, 1, buf, true); | 1269 | rc = fat_readwrite(&dir->file, 1, buf, true); |
1174 | if (rc < 1) | 1270 | if (rc < 1) |
1175 | return rc * 10 - 3; | 1271 | return rc * 10 - 3; |
1176 | } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); | 1272 | } while (dir->file.sectornum < (int)fat_bpb->bpb_secperclus); |
1177 | } | 1273 | } |
1178 | if (rc < 0) { | 1274 | if (rc < 0) { |
1179 | DEBUGF( "add_dir_entry() - Couldn't read dir" | 1275 | DEBUGF( "add_dir_entry() - Couldn't read dir" |
@@ -1277,7 +1373,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
1277 | if (rc < 1) | 1373 | if (rc < 1) |
1278 | return rc * 10 - 9; | 1374 | return rc * 10 - 9; |
1279 | memset(buf, 0, sizeof buf); | 1375 | memset(buf, 0, sizeof buf); |
1280 | } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); | 1376 | } while (dir->file.sectornum < (int)fat_bpb->bpb_secperclus); |
1281 | } | 1377 | } |
1282 | else | 1378 | else |
1283 | { | 1379 | { |
@@ -1288,7 +1384,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
1288 | if (rc < 1) | 1384 | if (rc < 1) |
1289 | return rc * 10 - 9; /* Same error code as above, can't be | 1385 | return rc * 10 - 9; /* Same error code as above, can't be |
1290 | more than -9 */ | 1386 | more than -9 */ |
1291 | } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); | 1387 | } while (dir->file.sectornum < (int)fat_bpb->bpb_secperclus); |
1292 | } | 1388 | } |
1293 | } | 1389 | } |
1294 | 1390 | ||
@@ -1368,7 +1464,7 @@ static int update_short_entry( struct fat_file* file, int size, int attr ) | |||
1368 | file->firstcluster, file->direntry, size); | 1464 | file->firstcluster, file->direntry, size); |
1369 | 1465 | ||
1370 | /* create a temporary file handle for the dir holding this file */ | 1466 | /* create a temporary file handle for the dir holding this file */ |
1371 | rc = fat_open(file->dircluster, &dir, NULL); | 1467 | rc = fat_open(IF_MV2(file->volume,) file->dircluster, &dir, NULL); |
1372 | if (rc < 0) | 1468 | if (rc < 0) |
1373 | return rc * 10 - 1; | 1469 | return rc * 10 - 1; |
1374 | 1470 | ||
@@ -1445,7 +1541,8 @@ static int parse_direntry(struct fat_direntry *de, const unsigned char *buf) | |||
1445 | return 1; | 1541 | return 1; |
1446 | } | 1542 | } |
1447 | 1543 | ||
1448 | int fat_open(unsigned int startcluster, | 1544 | int fat_open(IF_MV2(int volume,) |
1545 | unsigned int startcluster, | ||
1449 | struct fat_file *file, | 1546 | struct fat_file *file, |
1450 | const struct fat_dir* dir) | 1547 | const struct fat_dir* dir) |
1451 | { | 1548 | { |
@@ -1455,6 +1552,15 @@ int fat_open(unsigned int startcluster, | |||
1455 | file->clusternum = 0; | 1552 | file->clusternum = 0; |
1456 | file->sectornum = 0; | 1553 | file->sectornum = 0; |
1457 | file->eof = false; | 1554 | file->eof = false; |
1555 | #ifdef HAVE_MULTIVOLUME | ||
1556 | file->volume = volume; | ||
1557 | /* fixme: remove error check when done */ | ||
1558 | if (volume >= NUM_VOLUMES || !fat_bpbs[volume].mounted) | ||
1559 | { | ||
1560 | LDEBUGF("fat_open() illegal volume %d\n", volume); | ||
1561 | return -1; | ||
1562 | } | ||
1563 | #endif | ||
1458 | 1564 | ||
1459 | /* remember where the file's dir entry is located */ | 1565 | /* remember where the file's dir entry is located */ |
1460 | if ( dir ) { | 1566 | if ( dir ) { |
@@ -1469,19 +1575,26 @@ int fat_open(unsigned int startcluster, | |||
1469 | #ifdef HAVE_FAT16SUPPORT | 1575 | #ifdef HAVE_FAT16SUPPORT |
1470 | /* special function to open the FAT16 root dir, | 1576 | /* special function to open the FAT16 root dir, |
1471 | which may not be on cluster boundary */ | 1577 | which may not be on cluster boundary */ |
1472 | int fat_open_root(struct fat_file *file) | 1578 | static int fat_open_root(IF_MV2(int volume,) |
1579 | struct fat_file *file) | ||
1473 | { | 1580 | { |
1474 | int dirclusters; | 1581 | int dirclusters; |
1475 | file->firstcluster = fat_bpb.bpb_rootclus; | 1582 | #ifdef HAVE_MULTIVOLUME |
1476 | file->lastcluster = fat_bpb.bpb_rootclus; | 1583 | struct bpb* fat_bpb = &fat_bpbs[volume]; |
1584 | file->volume = volume; | ||
1585 | #else | ||
1586 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
1587 | #endif | ||
1588 | file->firstcluster = fat_bpb->bpb_rootclus; | ||
1589 | file->lastcluster = fat_bpb->bpb_rootclus; | ||
1477 | file->lastsector = 0; | 1590 | file->lastsector = 0; |
1478 | file->clusternum = 0; | 1591 | file->clusternum = 0; |
1479 | dirclusters = 0 - fat_bpb.bpb_rootclus; /* bpb_rootclus is the negative */ | 1592 | dirclusters = 0 - fat_bpb->bpb_rootclus; /* bpb_rootclus is the negative */ |
1480 | file->sectornum = (dirclusters * fat_bpb.bpb_secperclus) | 1593 | file->sectornum = (dirclusters * fat_bpb->bpb_secperclus) |
1481 | - fat_bpb.rootdirsectors; /* cluster sectors minus real sectors */ | 1594 | - fat_bpb->rootdirsectors; /* cluster sectors minus real sectors */ |
1482 | file->eof = false; | 1595 | file->eof = false; |
1483 | 1596 | ||
1484 | LDEBUGF("fat_open_root(), sector %d\n", cluster2sec(fat_bpb.bpb_rootclus)); | 1597 | LDEBUGF("fat_open_root(), sector %d\n", cluster2sec(fat_bpb->bpb_rootclus)); |
1485 | return 0; | 1598 | return 0; |
1486 | } | 1599 | } |
1487 | #endif /* #ifdef HAVE_FAT16SUPPORT */ | 1600 | #endif /* #ifdef HAVE_FAT16SUPPORT */ |
@@ -1510,6 +1623,11 @@ int fat_create_dir(const char* name, | |||
1510 | struct fat_dir* newdir, | 1623 | struct fat_dir* newdir, |
1511 | struct fat_dir* dir) | 1624 | struct fat_dir* dir) |
1512 | { | 1625 | { |
1626 | #ifdef HAVE_MULTIVOLUME | ||
1627 | struct bpb* fat_bpb = &fat_bpbs[dir->file.volume]; | ||
1628 | #else | ||
1629 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
1630 | #endif | ||
1513 | unsigned char buf[SECTOR_SIZE]; | 1631 | unsigned char buf[SECTOR_SIZE]; |
1514 | int i; | 1632 | int i; |
1515 | int sector; | 1633 | int sector; |
@@ -1527,17 +1645,17 @@ int fat_create_dir(const char* name, | |||
1527 | return rc * 10 - 1; | 1645 | return rc * 10 - 1; |
1528 | 1646 | ||
1529 | /* Allocate a new cluster for the directory */ | 1647 | /* Allocate a new cluster for the directory */ |
1530 | newdir->file.firstcluster = find_free_cluster(fat_bpb.fsinfo.nextfree); | 1648 | newdir->file.firstcluster = find_free_cluster(IF_MV2(fat_bpb,) fat_bpb->fsinfo.nextfree); |
1531 | if(newdir->file.firstcluster == 0) | 1649 | if(newdir->file.firstcluster == 0) |
1532 | return -1; | 1650 | return -1; |
1533 | 1651 | ||
1534 | update_fat_entry(newdir->file.firstcluster, FAT_EOF_MARK); | 1652 | update_fat_entry(IF_MV2(fat_bpb,) newdir->file.firstcluster, FAT_EOF_MARK); |
1535 | 1653 | ||
1536 | /* Clear the entire cluster */ | 1654 | /* Clear the entire cluster */ |
1537 | memset(buf, 0, sizeof buf); | 1655 | memset(buf, 0, sizeof buf); |
1538 | sector = cluster2sec(newdir->file.firstcluster); | 1656 | sector = cluster2sec(IF_MV2(fat_bpb,) newdir->file.firstcluster); |
1539 | for(i = 0;i < (int)fat_bpb.bpb_secperclus;i++) { | 1657 | for(i = 0;i < (int)fat_bpb->bpb_secperclus;i++) { |
1540 | rc = transfer( sector + i, 1, buf, true ); | 1658 | rc = transfer(IF_MV2(fat_bpb,) sector + i, 1, buf, true ); |
1541 | if (rc < 0) | 1659 | if (rc < 0) |
1542 | return rc * 10 - 2; | 1660 | return rc * 10 - 2; |
1543 | } | 1661 | } |
@@ -1555,7 +1673,7 @@ int fat_create_dir(const char* name, | |||
1555 | return rc * 10 - 4; | 1673 | return rc * 10 - 4; |
1556 | 1674 | ||
1557 | /* The root cluster is cluster 0 in the ".." entry */ | 1675 | /* The root cluster is cluster 0 in the ".." entry */ |
1558 | if(dir->file.firstcluster == fat_bpb.bpb_rootclus) | 1676 | if(dir->file.firstcluster == fat_bpb->bpb_rootclus) |
1559 | dummyfile.firstcluster = 0; | 1677 | dummyfile.firstcluster = 0; |
1560 | else | 1678 | else |
1561 | dummyfile.firstcluster = dir->file.firstcluster; | 1679 | dummyfile.firstcluster = dir->file.firstcluster; |
@@ -1564,7 +1682,7 @@ int fat_create_dir(const char* name, | |||
1564 | /* Set the firstcluster field in the direntry */ | 1682 | /* Set the firstcluster field in the direntry */ |
1565 | update_short_entry(&newdir->file, 0, FAT_ATTR_DIRECTORY); | 1683 | update_short_entry(&newdir->file, 0, FAT_ATTR_DIRECTORY); |
1566 | 1684 | ||
1567 | rc = flush_fat(); | 1685 | rc = flush_fat(IF_MV(fat_bpb)); |
1568 | if (rc < 0) | 1686 | if (rc < 0) |
1569 | return rc * 10 - 5; | 1687 | return rc * 10 - 5; |
1570 | 1688 | ||
@@ -1576,15 +1694,18 @@ int fat_truncate(const struct fat_file *file) | |||
1576 | /* truncate trailing clusters */ | 1694 | /* truncate trailing clusters */ |
1577 | int next; | 1695 | int next; |
1578 | int last = file->lastcluster; | 1696 | int last = file->lastcluster; |
1697 | #ifdef HAVE_MULTIVOLUME | ||
1698 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
1699 | #endif | ||
1579 | 1700 | ||
1580 | LDEBUGF("fat_truncate(%x, %x)\n", file->firstcluster, last); | 1701 | LDEBUGF("fat_truncate(%x, %x)\n", file->firstcluster, last); |
1581 | 1702 | ||
1582 | for ( last = get_next_cluster(last); last; last = next ) { | 1703 | for ( last = get_next_cluster(IF_MV2(fat_bpb,) last); last; last = next ) { |
1583 | next = get_next_cluster(last); | 1704 | next = get_next_cluster(IF_MV2(fat_bpb,) last); |
1584 | update_fat_entry(last,0); | 1705 | update_fat_entry(IF_MV2(fat_bpb,) last,0); |
1585 | } | 1706 | } |
1586 | if (file->lastcluster) | 1707 | if (file->lastcluster) |
1587 | update_fat_entry(file->lastcluster,FAT_EOF_MARK); | 1708 | update_fat_entry(IF_MV2(fat_bpb,) file->lastcluster,FAT_EOF_MARK); |
1588 | 1709 | ||
1589 | return 0; | 1710 | return 0; |
1590 | } | 1711 | } |
@@ -1592,12 +1713,15 @@ int fat_truncate(const struct fat_file *file) | |||
1592 | int fat_closewrite(struct fat_file *file, int size, int attr) | 1713 | int fat_closewrite(struct fat_file *file, int size, int attr) |
1593 | { | 1714 | { |
1594 | int rc; | 1715 | int rc; |
1716 | #ifdef HAVE_MULTIVOLUME | ||
1717 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
1718 | #endif | ||
1595 | LDEBUGF("fat_closewrite(size=%d)\n",size); | 1719 | LDEBUGF("fat_closewrite(size=%d)\n",size); |
1596 | 1720 | ||
1597 | if (!size) { | 1721 | if (!size) { |
1598 | /* empty file */ | 1722 | /* empty file */ |
1599 | if ( file->firstcluster ) { | 1723 | if ( file->firstcluster ) { |
1600 | update_fat_entry(file->firstcluster, 0); | 1724 | update_fat_entry(IF_MV2(fat_bpb,) file->firstcluster, 0); |
1601 | file->firstcluster = 0; | 1725 | file->firstcluster = 0; |
1602 | } | 1726 | } |
1603 | } | 1727 | } |
@@ -1608,21 +1732,26 @@ int fat_closewrite(struct fat_file *file, int size, int attr) | |||
1608 | return rc * 10 - 1; | 1732 | return rc * 10 - 1; |
1609 | } | 1733 | } |
1610 | 1734 | ||
1611 | flush_fat(); | 1735 | flush_fat(IF_MV(fat_bpb)); |
1612 | 1736 | ||
1613 | #ifdef TEST_FAT | 1737 | #ifdef TEST_FAT |
1614 | if ( file->firstcluster ) { | 1738 | if ( file->firstcluster ) { |
1615 | /* debug */ | 1739 | /* debug */ |
1740 | #ifdef HAVE_MULTIVOLUME | ||
1741 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
1742 | #else | ||
1743 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
1744 | #endif | ||
1616 | int count = 0; | 1745 | int count = 0; |
1617 | int len; | 1746 | int len; |
1618 | int next; | 1747 | int next; |
1619 | for ( next = file->firstcluster; next; | 1748 | for ( next = file->firstcluster; next; |
1620 | next = get_next_cluster(next) ) | 1749 | next = get_next_cluster(IF_MV2(fat_bpb,) next) ) |
1621 | LDEBUGF("cluster %d: %x\n", count++, next); | 1750 | LDEBUGF("cluster %d: %x\n", count++, next); |
1622 | len = count * fat_bpb.bpb_secperclus * SECTOR_SIZE; | 1751 | len = count * fat_bpb->bpb_secperclus * SECTOR_SIZE; |
1623 | LDEBUGF("File is %d clusters (chainlen=%d, size=%d)\n", | 1752 | LDEBUGF("File is %d clusters (chainlen=%d, size=%d)\n", |
1624 | count, len, size ); | 1753 | count, len, size ); |
1625 | if ( len > size + fat_bpb.bpb_secperclus * SECTOR_SIZE) | 1754 | if ( len > size + fat_bpb->bpb_secperclus * SECTOR_SIZE) |
1626 | panicf("Cluster chain is too long\n"); | 1755 | panicf("Cluster chain is too long\n"); |
1627 | if ( len < size ) | 1756 | if ( len < size ) |
1628 | panicf("Cluster chain is too short\n"); | 1757 | panicf("Cluster chain is too short\n"); |
@@ -1632,17 +1761,18 @@ int fat_closewrite(struct fat_file *file, int size, int attr) | |||
1632 | return 0; | 1761 | return 0; |
1633 | } | 1762 | } |
1634 | 1763 | ||
1635 | static int free_direntries(int dircluster, int startentry, int numentries) | 1764 | static int free_direntries(struct fat_file* file) |
1636 | { | 1765 | { |
1637 | unsigned char buf[SECTOR_SIZE]; | 1766 | unsigned char buf[SECTOR_SIZE]; |
1638 | struct fat_file dir; | 1767 | struct fat_file dir; |
1639 | unsigned int entry = startentry - numentries + 1; | 1768 | int numentries = file->direntries; |
1769 | unsigned int entry = file->direntry - numentries + 1; | ||
1640 | unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; | 1770 | unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; |
1641 | int i; | 1771 | int i; |
1642 | int rc; | 1772 | int rc; |
1643 | 1773 | ||
1644 | /* create a temporary file handle for the dir holding this file */ | 1774 | /* create a temporary file handle for the dir holding this file */ |
1645 | rc = fat_open(dircluster, &dir, NULL); | 1775 | rc = fat_open(IF_MV2(file->volume,) file->dircluster, &dir, NULL); |
1646 | if (rc < 0) | 1776 | if (rc < 0) |
1647 | return rc * 10 - 1; | 1777 | return rc * 10 - 1; |
1648 | 1778 | ||
@@ -1698,19 +1828,20 @@ int fat_remove(struct fat_file* file) | |||
1698 | { | 1828 | { |
1699 | int next, last = file->firstcluster; | 1829 | int next, last = file->firstcluster; |
1700 | int rc; | 1830 | int rc; |
1831 | #ifdef HAVE_MULTIVOLUME | ||
1832 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
1833 | #endif | ||
1701 | 1834 | ||
1702 | LDEBUGF("fat_remove(%x)\n",last); | 1835 | LDEBUGF("fat_remove(%x)\n",last); |
1703 | 1836 | ||
1704 | while ( last ) { | 1837 | while ( last ) { |
1705 | next = get_next_cluster(last); | 1838 | next = get_next_cluster(IF_MV2(fat_bpb,) last); |
1706 | update_fat_entry(last,0); | 1839 | update_fat_entry(IF_MV2(fat_bpb,) last,0); |
1707 | last = next; | 1840 | last = next; |
1708 | } | 1841 | } |
1709 | 1842 | ||
1710 | if ( file->dircluster ) { | 1843 | if ( file->dircluster ) { |
1711 | rc = free_direntries(file->dircluster, | 1844 | rc = free_direntries(file); |
1712 | file->direntry, | ||
1713 | file->direntries); | ||
1714 | if (rc < 0) | 1845 | if (rc < 0) |
1715 | return rc * 10 - 1; | 1846 | return rc * 10 - 1; |
1716 | } | 1847 | } |
@@ -1718,7 +1849,7 @@ int fat_remove(struct fat_file* file) | |||
1718 | file->firstcluster = 0; | 1849 | file->firstcluster = 0; |
1719 | file->dircluster = 0; | 1850 | file->dircluster = 0; |
1720 | 1851 | ||
1721 | rc = flush_fat(); | 1852 | rc = flush_fat(IF_MV(fat_bpb)); |
1722 | if (rc < 0) | 1853 | if (rc < 0) |
1723 | return rc * 10 - 2; | 1854 | return rc * 10 - 2; |
1724 | 1855 | ||
@@ -1734,6 +1865,9 @@ int fat_rename(struct fat_file* file, | |||
1734 | int rc; | 1865 | int rc; |
1735 | struct fat_dir olddir; | 1866 | struct fat_dir olddir; |
1736 | struct fat_file newfile = *file; | 1867 | struct fat_file newfile = *file; |
1868 | #ifdef HAVE_MULTIVOLUME | ||
1869 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
1870 | #endif | ||
1737 | 1871 | ||
1738 | if ( !file->dircluster ) { | 1872 | if ( !file->dircluster ) { |
1739 | DEBUGF("File has no dir cluster!\n"); | 1873 | DEBUGF("File has no dir cluster!\n"); |
@@ -1741,7 +1875,7 @@ int fat_rename(struct fat_file* file, | |||
1741 | } | 1875 | } |
1742 | 1876 | ||
1743 | /* create a temporary file handle */ | 1877 | /* create a temporary file handle */ |
1744 | rc = fat_opendir(&olddir, file->dircluster, NULL); | 1878 | rc = fat_opendir(IF_MV2(file->volume,) &olddir, file->dircluster, NULL); |
1745 | if (rc < 0) | 1879 | if (rc < 0) |
1746 | return rc * 10 - 2; | 1880 | return rc * 10 - 2; |
1747 | 1881 | ||
@@ -1756,11 +1890,11 @@ int fat_rename(struct fat_file* file, | |||
1756 | return rc * 10 - 4; | 1890 | return rc * 10 - 4; |
1757 | 1891 | ||
1758 | /* remove old name */ | 1892 | /* remove old name */ |
1759 | rc = free_direntries(file->dircluster, file->direntry, file->direntries); | 1893 | rc = free_direntries(file); |
1760 | if (rc < 0) | 1894 | if (rc < 0) |
1761 | return rc * 10 - 5; | 1895 | return rc * 10 - 5; |
1762 | 1896 | ||
1763 | rc = flush_fat(); | 1897 | rc = flush_fat(IF_MV(fat_bpb)); |
1764 | if (rc < 0) | 1898 | if (rc < 0) |
1765 | return rc * 10 - 6; | 1899 | return rc * 10 - 6; |
1766 | 1900 | ||
@@ -1771,19 +1905,24 @@ static int next_write_cluster(struct fat_file* file, | |||
1771 | int oldcluster, | 1905 | int oldcluster, |
1772 | int* newsector) | 1906 | int* newsector) |
1773 | { | 1907 | { |
1908 | #ifdef HAVE_MULTIVOLUME | ||
1909 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
1910 | #else | ||
1911 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
1912 | #endif | ||
1774 | int cluster = 0; | 1913 | int cluster = 0; |
1775 | int sector; | 1914 | int sector; |
1776 | 1915 | ||
1777 | LDEBUGF("next_write_cluster(%x,%x)\n",file->firstcluster, oldcluster); | 1916 | LDEBUGF("next_write_cluster(%x,%x)\n",file->firstcluster, oldcluster); |
1778 | 1917 | ||
1779 | if (oldcluster) | 1918 | if (oldcluster) |
1780 | cluster = get_next_cluster(oldcluster); | 1919 | cluster = get_next_cluster(IF_MV2(fat_bpb,) oldcluster); |
1781 | 1920 | ||
1782 | if (!cluster) { | 1921 | if (!cluster) { |
1783 | if (oldcluster > 0) | 1922 | if (oldcluster > 0) |
1784 | cluster = find_free_cluster(oldcluster+1); | 1923 | cluster = find_free_cluster(IF_MV2(fat_bpb,) oldcluster+1); |
1785 | else if (oldcluster == 0) | 1924 | else if (oldcluster == 0) |
1786 | cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); | 1925 | cluster = find_free_cluster(IF_MV2(fat_bpb,) fat_bpb->fsinfo.nextfree); |
1787 | #ifdef HAVE_FAT16SUPPORT | 1926 | #ifdef HAVE_FAT16SUPPORT |
1788 | else /* negative, pseudo-cluster of the root dir */ | 1927 | else /* negative, pseudo-cluster of the root dir */ |
1789 | return 0; /* impossible to append something to the root */ | 1928 | return 0; /* impossible to append something to the root */ |
@@ -1791,14 +1930,14 @@ static int next_write_cluster(struct fat_file* file, | |||
1791 | 1930 | ||
1792 | if (cluster) { | 1931 | if (cluster) { |
1793 | if (oldcluster) | 1932 | if (oldcluster) |
1794 | update_fat_entry(oldcluster, cluster); | 1933 | update_fat_entry(IF_MV2(fat_bpb,) oldcluster, cluster); |
1795 | else | 1934 | else |
1796 | file->firstcluster = cluster; | 1935 | file->firstcluster = cluster; |
1797 | update_fat_entry(cluster, FAT_EOF_MARK); | 1936 | update_fat_entry(IF_MV2(fat_bpb,) cluster, FAT_EOF_MARK); |
1798 | } | 1937 | } |
1799 | else { | 1938 | else { |
1800 | #ifdef TEST_FAT | 1939 | #ifdef TEST_FAT |
1801 | if (fat_bpb.fsinfo.freecount>0) | 1940 | if (fat_bpb->fsinfo.freecount>0) |
1802 | panicf("There is free space, but find_free_cluster() " | 1941 | panicf("There is free space, but find_free_cluster() " |
1803 | "didn't find it!\n"); | 1942 | "didn't find it!\n"); |
1804 | #endif | 1943 | #endif |
@@ -1806,7 +1945,7 @@ static int next_write_cluster(struct fat_file* file, | |||
1806 | return 0; | 1945 | return 0; |
1807 | } | 1946 | } |
1808 | } | 1947 | } |
1809 | sector = cluster2sec(cluster); | 1948 | sector = cluster2sec(IF_MV2(fat_bpb,) cluster); |
1810 | if (sector<0) | 1949 | if (sector<0) |
1811 | return 0; | 1950 | return 0; |
1812 | 1951 | ||
@@ -1814,30 +1953,36 @@ static int next_write_cluster(struct fat_file* file, | |||
1814 | return cluster; | 1953 | return cluster; |
1815 | } | 1954 | } |
1816 | 1955 | ||
1817 | static int transfer( unsigned int start, int count, char* buf, bool write ) | 1956 | static int transfer(IF_MV2(struct bpb* fat_bpb,) |
1957 | unsigned int start, int count, char* buf, bool write ) | ||
1818 | { | 1958 | { |
1959 | #ifndef HAVE_MULTIVOLUME | ||
1960 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
1961 | #endif | ||
1819 | int rc; | 1962 | int rc; |
1820 | 1963 | ||
1821 | LDEBUGF("transfer(s=%x, c=%x, %s)\n", | 1964 | LDEBUGF("transfer(s=%x, c=%x, %s)\n", |
1822 | start+ fat_bpb.startsector, count, write?"write":"read"); | 1965 | start+ fat_bpb->startsector, count, write?"write":"read"); |
1823 | if (write) { | 1966 | if (write) { |
1824 | unsigned int firstallowed; | 1967 | unsigned int firstallowed; |
1825 | #ifdef HAVE_FAT16SUPPORT | 1968 | #ifdef HAVE_FAT16SUPPORT |
1826 | if (fat_bpb.is_fat16) | 1969 | if (fat_bpb->is_fat16) |
1827 | firstallowed = fat_bpb.rootdirsector; | 1970 | firstallowed = fat_bpb->rootdirsector; |
1828 | else | 1971 | else |
1829 | #endif | 1972 | #endif |
1830 | firstallowed = fat_bpb.firstdatasector; | 1973 | firstallowed = fat_bpb->firstdatasector; |
1831 | 1974 | ||
1832 | if (start < firstallowed) | 1975 | if (start < firstallowed) |
1833 | panicf("Write %d before data\n", firstallowed - start); | 1976 | panicf("Write %d before data\n", firstallowed - start); |
1834 | if (start + count > fat_bpb.totalsectors) | 1977 | if (start + count > fat_bpb->totalsectors) |
1835 | panicf("Write %d after data\n", | 1978 | panicf("Write %d after data\n", |
1836 | start + count - fat_bpb.totalsectors); | 1979 | start + count - fat_bpb->totalsectors); |
1837 | rc = ata_write_sectors(start + fat_bpb.startsector, count, buf); | 1980 | rc = ata_write_sectors(IF_MV2(fat_bpb->drive,) |
1981 | start + fat_bpb->startsector, count, buf); | ||
1838 | } | 1982 | } |
1839 | else | 1983 | else |
1840 | rc = ata_read_sectors(start + fat_bpb.startsector, count, buf); | 1984 | rc = ata_read_sectors(IF_MV2(fat_bpb->drive,) |
1985 | start + fat_bpb->startsector, count, buf); | ||
1841 | if (rc < 0) { | 1986 | if (rc < 0) { |
1842 | DEBUGF( "transfer() - Couldn't %s sector %x" | 1987 | DEBUGF( "transfer() - Couldn't %s sector %x" |
1843 | " (error code %d)\n", | 1988 | " (error code %d)\n", |
@@ -1851,6 +1996,11 @@ static int transfer( unsigned int start, int count, char* buf, bool write ) | |||
1851 | int fat_readwrite( struct fat_file *file, int sectorcount, | 1996 | int fat_readwrite( struct fat_file *file, int sectorcount, |
1852 | void* buf, bool write ) | 1997 | void* buf, bool write ) |
1853 | { | 1998 | { |
1999 | #ifdef HAVE_MULTIVOLUME | ||
2000 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
2001 | #else | ||
2002 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
2003 | #endif | ||
1854 | int cluster = file->lastcluster; | 2004 | int cluster = file->lastcluster; |
1855 | int sector = file->lastsector; | 2005 | int sector = file->lastsector; |
1856 | int clusternum = file->clusternum; | 2006 | int clusternum = file->clusternum; |
@@ -1871,13 +2021,13 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1871 | /* find sequential sectors and write them all at once */ | 2021 | /* find sequential sectors and write them all at once */ |
1872 | for (i=0; (i < sectorcount) && (sector > -1); i++ ) { | 2022 | for (i=0; (i < sectorcount) && (sector > -1); i++ ) { |
1873 | numsec++; | 2023 | numsec++; |
1874 | if ( numsec > (int)fat_bpb.bpb_secperclus || !cluster ) { | 2024 | if ( numsec > (int)fat_bpb->bpb_secperclus || !cluster ) { |
1875 | int oldcluster = cluster; | 2025 | int oldcluster = cluster; |
1876 | if (write) | 2026 | if (write) |
1877 | cluster = next_write_cluster(file, cluster, §or); | 2027 | cluster = next_write_cluster(file, cluster, §or); |
1878 | else { | 2028 | else { |
1879 | cluster = get_next_cluster(cluster); | 2029 | cluster = get_next_cluster(IF_MV2(fat_bpb,) cluster); |
1880 | sector = cluster2sec(cluster); | 2030 | sector = cluster2sec(IF_MV2(fat_bpb,) cluster); |
1881 | } | 2031 | } |
1882 | 2032 | ||
1883 | clusternum++; | 2033 | clusternum++; |
@@ -1902,7 +2052,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1902 | sector++; | 2052 | sector++; |
1903 | else { | 2053 | else { |
1904 | /* look up first sector of file */ | 2054 | /* look up first sector of file */ |
1905 | sector = cluster2sec(file->firstcluster); | 2055 | sector = cluster2sec(IF_MV2(fat_bpb,) file->firstcluster); |
1906 | numsec=1; | 2056 | numsec=1; |
1907 | } | 2057 | } |
1908 | } | 2058 | } |
@@ -1913,7 +2063,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1913 | if ( ((sector != first) && (sector != last+1)) || /* not sequential */ | 2063 | if ( ((sector != first) && (sector != last+1)) || /* not sequential */ |
1914 | (last-first+1 == 256) ) { /* max 256 sectors per ata request */ | 2064 | (last-first+1 == 256) ) { /* max 256 sectors per ata request */ |
1915 | int count = last - first + 1; | 2065 | int count = last - first + 1; |
1916 | rc = transfer( first, count, buf, write ); | 2066 | rc = transfer(IF_MV2(fat_bpb,) first, count, buf, write ); |
1917 | if (rc < 0) | 2067 | if (rc < 0) |
1918 | return rc * 10 - 1; | 2068 | return rc * 10 - 1; |
1919 | 2069 | ||
@@ -1925,7 +2075,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1925 | (!eof)) | 2075 | (!eof)) |
1926 | { | 2076 | { |
1927 | int count = sector - first + 1; | 2077 | int count = sector - first + 1; |
1928 | rc = transfer( first, count, buf, write ); | 2078 | rc = transfer(IF_MV2(fat_bpb,) first, count, buf, write ); |
1929 | if (rc < 0) | 2079 | if (rc < 0) |
1930 | return rc * 10 - 2; | 2080 | return rc * 10 - 2; |
1931 | } | 2081 | } |
@@ -1949,6 +2099,11 @@ int fat_readwrite( struct fat_file *file, int sectorcount, | |||
1949 | 2099 | ||
1950 | int fat_seek(struct fat_file *file, unsigned int seeksector ) | 2100 | int fat_seek(struct fat_file *file, unsigned int seeksector ) |
1951 | { | 2101 | { |
2102 | #ifdef HAVE_MULTIVOLUME | ||
2103 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | ||
2104 | #else | ||
2105 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
2106 | #endif | ||
1952 | int clusternum=0, numclusters=0, sectornum=0, sector=0; | 2107 | int clusternum=0, numclusters=0, sectornum=0, sector=0; |
1953 | int cluster = file->firstcluster; | 2108 | int cluster = file->firstcluster; |
1954 | int i; | 2109 | int i; |
@@ -1958,8 +2113,8 @@ int fat_seek(struct fat_file *file, unsigned int seeksector ) | |||
1958 | /* we need to find the sector BEFORE the requested, since | 2113 | /* we need to find the sector BEFORE the requested, since |
1959 | the file struct stores the last accessed sector */ | 2114 | the file struct stores the last accessed sector */ |
1960 | seeksector--; | 2115 | seeksector--; |
1961 | numclusters = clusternum = seeksector / fat_bpb.bpb_secperclus; | 2116 | numclusters = clusternum = seeksector / fat_bpb->bpb_secperclus; |
1962 | sectornum = seeksector % fat_bpb.bpb_secperclus; | 2117 | sectornum = seeksector % fat_bpb->bpb_secperclus; |
1963 | 2118 | ||
1964 | if (file->clusternum && clusternum >= file->clusternum) | 2119 | if (file->clusternum && clusternum >= file->clusternum) |
1965 | { | 2120 | { |
@@ -1968,7 +2123,7 @@ int fat_seek(struct fat_file *file, unsigned int seeksector ) | |||
1968 | } | 2123 | } |
1969 | 2124 | ||
1970 | for (i=0; i<numclusters; i++) { | 2125 | for (i=0; i<numclusters; i++) { |
1971 | cluster = get_next_cluster(cluster); | 2126 | cluster = get_next_cluster(IF_MV2(fat_bpb,) cluster); |
1972 | if (!cluster) { | 2127 | if (!cluster) { |
1973 | DEBUGF("Seeking beyond the end of the file! " | 2128 | DEBUGF("Seeking beyond the end of the file! " |
1974 | "(sector %d, cluster %d)\n", seeksector, i); | 2129 | "(sector %d, cluster %d)\n", seeksector, i); |
@@ -1976,7 +2131,7 @@ int fat_seek(struct fat_file *file, unsigned int seeksector ) | |||
1976 | } | 2131 | } |
1977 | } | 2132 | } |
1978 | 2133 | ||
1979 | sector = cluster2sec(cluster) + sectornum; | 2134 | sector = cluster2sec(IF_MV2(fat_bpb,) cluster) + sectornum; |
1980 | } | 2135 | } |
1981 | else { | 2136 | else { |
1982 | sectornum = -1; | 2137 | sectornum = -1; |
@@ -1992,9 +2147,21 @@ int fat_seek(struct fat_file *file, unsigned int seeksector ) | |||
1992 | return 0; | 2147 | return 0; |
1993 | } | 2148 | } |
1994 | 2149 | ||
1995 | int fat_opendir(struct fat_dir *dir, unsigned int startcluster, | 2150 | int fat_opendir(IF_MV2(int volume,) |
2151 | struct fat_dir *dir, unsigned int startcluster, | ||
1996 | const struct fat_dir *parent_dir) | 2152 | const struct fat_dir *parent_dir) |
1997 | { | 2153 | { |
2154 | #ifdef HAVE_MULTIVOLUME | ||
2155 | struct bpb* fat_bpb = &fat_bpbs[volume]; | ||
2156 | /* fixme: remove error check when done */ | ||
2157 | if (volume >= NUM_VOLUMES || !fat_bpbs[volume].mounted) | ||
2158 | { | ||
2159 | LDEBUGF("fat_open() illegal volume %d\n", volume); | ||
2160 | return -1; | ||
2161 | } | ||
2162 | #else | ||
2163 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
2164 | #endif | ||
1998 | int rc; | 2165 | int rc; |
1999 | 2166 | ||
2000 | dir->entry = 0; | 2167 | dir->entry = 0; |
@@ -2003,15 +2170,15 @@ int fat_opendir(struct fat_dir *dir, unsigned int startcluster, | |||
2003 | if (startcluster == 0) | 2170 | if (startcluster == 0) |
2004 | { | 2171 | { |
2005 | #ifdef HAVE_FAT16SUPPORT | 2172 | #ifdef HAVE_FAT16SUPPORT |
2006 | if (fat_bpb.is_fat16) | 2173 | if (fat_bpb->is_fat16) |
2007 | { /* FAT16 has the root dir outside of the data area */ | 2174 | { /* FAT16 has the root dir outside of the data area */ |
2008 | return fat_open_root(&dir->file); | 2175 | return fat_open_root(IF_MV2(volume,) &dir->file); |
2009 | } | 2176 | } |
2010 | #endif | 2177 | #endif |
2011 | startcluster = sec2cluster(fat_bpb.rootdirsector); | 2178 | startcluster = sec2cluster(IF_MV2(fat_bpb,) fat_bpb->rootdirsector); |
2012 | } | 2179 | } |
2013 | 2180 | ||
2014 | rc = fat_open(startcluster, &dir->file, parent_dir); | 2181 | rc = fat_open(IF_MV2(volume,) startcluster, &dir->file, parent_dir); |
2015 | if(rc) | 2182 | if(rc) |
2016 | { | 2183 | { |
2017 | DEBUGF( "fat_opendir() - Couldn't open dir" | 2184 | DEBUGF( "fat_opendir() - Couldn't open dir" |
@@ -2196,7 +2363,18 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
2196 | return 0; | 2363 | return 0; |
2197 | } | 2364 | } |
2198 | 2365 | ||
2199 | int fat_get_cluster_size(void) | 2366 | int fat_get_cluster_size(IF_MV_NONVOID(int volume)) |
2367 | { | ||
2368 | #ifndef HAVE_MULTIVOLUME | ||
2369 | const int volume = 0; | ||
2370 | #endif | ||
2371 | struct bpb* fat_bpb = &fat_bpbs[volume]; | ||
2372 | return fat_bpb->bpb_secperclus * SECTOR_SIZE; | ||
2373 | } | ||
2374 | |||
2375 | #ifdef HAVE_MULTIVOLUME | ||
2376 | bool fat_ismounted(int volume) | ||
2200 | { | 2377 | { |
2201 | return fat_bpb.bpb_secperclus * SECTOR_SIZE; | 2378 | return (volume<NUM_VOLUMES && fat_bpbs[volume].mounted); |
2202 | } | 2379 | } |
2380 | #endif | ||