summaryrefslogtreecommitdiff
path: root/firmware/drivers/fat.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r--firmware/drivers/fat.c734
1 files changed, 456 insertions, 278 deletions
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
224static struct bpb fat_bpb; 228static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
225 229
226static int update_fsinfo(void); 230static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
227static int first_sector_of_cluster(int cluster); 231static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb));
228static int bpb_is_sane(void); 232static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster);
229static void *cache_fat_sector(int secnum); 233static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int secnum);
230static int create_dos_name(const unsigned char *name, unsigned char *newname); 234static int create_dos_name(const unsigned char *name, unsigned char *newname);
231static unsigned int find_free_cluster(unsigned int start); 235static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int start);
232static int transfer( unsigned int start, int count, char* buf, bool write ); 236static 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
244static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE]; 251static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE];
245static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; 252static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
246 253
247static int sec2cluster(unsigned int sec) 254static 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
258static int cluster2sec(int cluster) 268static 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
273static int first_sector_of_cluster(int cluster) 286static 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
284int fat_startsector(void) 300int 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
289void fat_size(unsigned int* size, unsigned int* free) 309void 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
297int fat_mount(int startsector) 321void 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
343int 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
445void fat_recalc_free(void) 495void 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
491static int bpb_is_sane(void) 545static 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
537static void *cache_fat_sector(int fatsector) 594static 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
641static 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
594static unsigned int find_free_cluster(unsigned int startcluster) 688static 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
661static int update_fat_entry(unsigned int entry, unsigned int val) 758static 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
744static int read_fat_entry(unsigned int entry) 844static 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
780static int get_next_cluster(int cluster) 883static 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
802static int update_fsinfo(void) 908static 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
836static int flush_fat(void) 947static 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
1448int fat_open(unsigned int startcluster, 1544int 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 */
1472int fat_open_root(struct fat_file *file) 1578static 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)
1592int fat_closewrite(struct fat_file *file, int size, int attr) 1713int 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
1635static int free_direntries(int dircluster, int startentry, int numentries) 1764static 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
1817static int transfer( unsigned int start, int count, char* buf, bool write ) 1956static 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 )
1851int fat_readwrite( struct fat_file *file, int sectorcount, 1996int 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, &sector); 2027 cluster = next_write_cluster(file, cluster, &sector);
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
1950int fat_seek(struct fat_file *file, unsigned int seeksector ) 2100int 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
1995int fat_opendir(struct fat_dir *dir, unsigned int startcluster, 2150int 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
2199int fat_get_cluster_size(void) 2366int 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
2376bool 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