summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/common/dir.c83
-rw-r--r--firmware/common/disk.c26
-rw-r--r--firmware/common/file.c3
-rw-r--r--firmware/drivers/ata.c11
-rw-r--r--firmware/drivers/ata_mmc.c32
-rw-r--r--firmware/drivers/fat.c734
-rw-r--r--firmware/export/ata.h19
-rw-r--r--firmware/export/disk.h4
-rw-r--r--firmware/export/fat.h23
-rw-r--r--firmware/include/dir.h4
-rw-r--r--firmware/test/fat/main.c4
-rw-r--r--firmware/test/i2c/main.c641
-rw-r--r--firmware/usb.c27
13 files changed, 1291 insertions, 320 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index 1bad9327f6..5fa5f9db6e 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -23,11 +23,48 @@
23#include "fat.h" 23#include "fat.h"
24#include "dir.h" 24#include "dir.h"
25#include "debug.h" 25#include "debug.h"
26#include "atoi.h"
26 27
27#define MAX_OPEN_DIRS 8 28#define MAX_OPEN_DIRS 8
28 29
29static DIR opendirs[MAX_OPEN_DIRS]; 30static DIR opendirs[MAX_OPEN_DIRS];
30 31
32#ifdef HAVE_MULTIVOLUME
33
34/* how to name volumes, first char must be outside of legal file names,
35 a number gets appended to enumerate, if applicable */
36#ifdef HAVE_MMC
37static const char* vol_names = ":MMC";
38#else
39static const char* vol_names = ":HD";
40#endif
41
42/* returns on which volume this is, and copies the reduced name
43 (sortof a preprocessor for volume-decorated pathnames) */
44static int strip_volume(const char* name, char* namecopy)
45{
46 int volume = 0;
47
48 if (name[1] == vol_names[0] ) /* a colon identifies our volumes */
49 {
50 const char* temp;
51 temp = name + 1 + strlen(vol_names); /* behind special name */
52 volume = atoi(temp); /* number is following */
53 temp = strchr(temp, '/'); /* search for slash behind */
54 if (temp != NULL)
55 name = temp; /* use the part behind the volume */
56 else
57 name = "/"; /* else this must be the root dir */
58 }
59
60 strncpy(namecopy, name, MAX_PATH);
61 namecopy[MAX_PATH-1] = '\0';
62
63 return volume;
64}
65#endif /* #ifdef HAVE_MULTIVOLUME */
66
67
31DIR* opendir(const char* name) 68DIR* opendir(const char* name)
32{ 69{
33 char namecopy[MAX_PATH]; 70 char namecopy[MAX_PATH];
@@ -35,6 +72,9 @@ DIR* opendir(const char* name)
35 char* end; 72 char* end;
36 struct fat_direntry entry; 73 struct fat_direntry entry;
37 int dd; 74 int dd;
75#ifdef HAVE_MULTIVOLUME
76 int volume;
77#endif
38 78
39 /* find a free dir descriptor */ 79 /* find a free dir descriptor */
40 for ( dd=0; dd<MAX_OPEN_DIRS; dd++ ) 80 for ( dd=0; dd<MAX_OPEN_DIRS; dd++ )
@@ -55,15 +95,21 @@ DIR* opendir(const char* name)
55 return NULL; 95 return NULL;
56 } 96 }
57 97
58 if ( fat_opendir(&(opendirs[dd].fatdir), 0, NULL) < 0 ) { 98#ifdef HAVE_MULTIVOLUME
99 /* try to extract a heading volume name, if present */
100 volume = strip_volume(name, namecopy);
101 opendirs[dd].volumecounter = 0;
102#else
103 strncpy(namecopy,name,sizeof(namecopy)); /* just copy */
104 namecopy[sizeof(namecopy)-1] = '\0';
105#endif
106
107 if ( fat_opendir(IF_MV2(volume,) &(opendirs[dd].fatdir), 0, NULL) < 0 ) {
59 DEBUGF("Failed opening root dir\n"); 108 DEBUGF("Failed opening root dir\n");
60 opendirs[dd].busy = false; 109 opendirs[dd].busy = false;
61 return NULL; 110 return NULL;
62 } 111 }
63 112
64 strncpy(namecopy,name,sizeof(namecopy));
65 namecopy[sizeof(namecopy)-1] = 0;
66
67 for ( part = strtok_r(namecopy, "/", &end); part; 113 for ( part = strtok_r(namecopy, "/", &end); part;
68 part = strtok_r(NULL, "/", &end)) { 114 part = strtok_r(NULL, "/", &end)) {
69 /* scan dir for name */ 115 /* scan dir for name */
@@ -76,7 +122,8 @@ DIR* opendir(const char* name)
76 if ( (entry.attr & FAT_ATTR_DIRECTORY) && 122 if ( (entry.attr & FAT_ATTR_DIRECTORY) &&
77 (!strcasecmp(part, entry.name)) ) { 123 (!strcasecmp(part, entry.name)) ) {
78 opendirs[dd].parent_dir = opendirs[dd].fatdir; 124 opendirs[dd].parent_dir = opendirs[dd].fatdir;
79 if ( fat_opendir(&(opendirs[dd].fatdir), 125 if ( fat_opendir(IF_MV2(volume,)
126 &(opendirs[dd].fatdir),
80 entry.firstcluster, 127 entry.firstcluster,
81 &(opendirs[dd].parent_dir)) < 0 ) { 128 &(opendirs[dd].parent_dir)) < 0 ) {
82 DEBUGF("Failed opening dir '%s' (%d)\n", 129 DEBUGF("Failed opening dir '%s' (%d)\n",
@@ -84,6 +131,9 @@ DIR* opendir(const char* name)
84 opendirs[dd].busy = false; 131 opendirs[dd].busy = false;
85 return NULL; 132 return NULL;
86 } 133 }
134#ifdef HAVE_MULTIVOLUME
135 opendirs[dd].volumecounter = -1; /* n.a. to subdirs */
136#endif
87 break; 137 break;
88 } 138 }
89 } 139 }
@@ -102,7 +152,28 @@ struct dirent* readdir(DIR* dir)
102{ 152{
103 struct fat_direntry entry; 153 struct fat_direntry entry;
104 struct dirent* theent = &(dir->theent); 154 struct dirent* theent = &(dir->theent);
105 155#ifdef HAVE_MULTIVOLUME
156 /* Volumes (secondary file systems) get inserted into the root directory
157 of the first volume, since we have no separate top level. */
158 if (dir->volumecounter >= 0 /* on a root dir */
159 && dir->volumecounter < NUM_VOLUMES /* in range */
160 && dir->fatdir.file.volume == 0) /* at volume 0 */
161 { /* fake special directories, which don't really exist, but
162 will get redirected upon opendir() */
163 while (++dir->volumecounter < NUM_VOLUMES)
164 {
165 if (fat_ismounted(dir->volumecounter))
166 {
167 memset(theent, 0, sizeof(*theent));
168 theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
169 snprintf(theent->d_name, sizeof(theent->d_name),
170 "%s%d", vol_names, dir->volumecounter);
171 return theent;
172 }
173 }
174 }
175#endif
176 /* normal directory entry fetching follows here */
106 if (fat_getnext(&(dir->fatdir),&entry) < 0) 177 if (fat_getnext(&(dir->fatdir),&entry) < 0)
107 return NULL; 178 return NULL;
108 179
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index b85f460a69..cfe15984f9 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -41,12 +41,22 @@
41 41
42static struct partinfo part[8]; 42static struct partinfo part[8];
43 43
44struct partinfo* disk_init(void) 44struct partinfo* disk_init(IF_MV_NONVOID(int drive))
45{ 45{
46 int i; 46 int i;
47 unsigned char sector[512]; 47 unsigned char sector[512];
48#ifdef HAVE_MULTIVOLUME
49 /* For each drive, start at a different position, in order not to destroy
50 the first entry of drive 0.
51 That one is needed to calculate config sector position. */
52 struct partinfo* pinfo = &part[drive*4];
53 if ((size_t)drive >= sizeof(part)/sizeof(*part)/4)
54 return NULL; /* out of space in table */
55#else
56 struct partinfo* pinfo = part;
57#endif
48 58
49 ata_read_sectors(0,1,&sector); 59 ata_read_sectors(IF_MV2(drive,) 0,1,&sector);
50 60
51 /* check that the boot sector is initialized */ 61 /* check that the boot sector is initialized */
52 if ( (sector[510] != 0x55) || 62 if ( (sector[510] != 0x55) ||
@@ -58,20 +68,20 @@ struct partinfo* disk_init(void)
58 /* parse partitions */ 68 /* parse partitions */
59 for ( i=0; i<4; i++ ) { 69 for ( i=0; i<4; i++ ) {
60 unsigned char* ptr = sector + 0x1be + 16*i; 70 unsigned char* ptr = sector + 0x1be + 16*i;
61 part[i].type = ptr[4]; 71 pinfo[i].type = ptr[4];
62 part[i].start = BYTES2INT32(ptr, 8); 72 pinfo[i].start = BYTES2INT32(ptr, 8);
63 part[i].size = BYTES2INT32(ptr, 12); 73 pinfo[i].size = BYTES2INT32(ptr, 12);
64 74
65 DEBUGF("Part%d: Type %02x, start: %08x size: %08x\n", 75 DEBUGF("Part%d: Type %02x, start: %08x size: %08x\n",
66 i,part[i].type,part[i].start,part[i].size); 76 i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
67 77
68 /* extended? */ 78 /* extended? */
69 if ( part[i].type == 5 ) { 79 if ( pinfo[i].type == 5 ) {
70 /* not handled yet */ 80 /* not handled yet */
71 } 81 }
72 } 82 }
73 83
74 return part; 84 return pinfo;
75} 85}
76 86
77struct partinfo* disk_partinfo(int partition) 87struct partinfo* disk_partinfo(int partition)
diff --git a/firmware/common/file.c b/firmware/common/file.c
index 81b5a194c0..6714b9982c 100644
--- a/firmware/common/file.c
+++ b/firmware/common/file.c
@@ -132,7 +132,8 @@ int open(const char* pathname, int flags)
132 /* scan dir for name */ 132 /* scan dir for name */
133 while ((entry = readdir(dir))) { 133 while ((entry = readdir(dir))) {
134 if ( !strcasecmp(name, entry->d_name) ) { 134 if ( !strcasecmp(name, entry->d_name) ) {
135 fat_open(entry->startcluster, 135 fat_open(IF_MV2(dir->fatdir.file.volume,)
136 entry->startcluster,
136 &(file->fatfile), 137 &(file->fatfile),
137 &(dir->fatdir)); 138 &(dir->fatdir));
138 file->size = file->trunc ? 0 : entry->size; 139 file->size = file->trunc ? 0 : entry->size;
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
313int ata_read_sectors(unsigned long start, 313int 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
579int ata_write_sectors(unsigned long start, 580int 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) */
672extern void ata_delayed_write(unsigned long sector, const void* buf) 676extern 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 */
679extern void ata_flush(void) 684extern 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
611int ata_read_sectors(unsigned long start, 611int 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
666int ata_write_sectors(unsigned long start, 673int 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 */
736extern void ata_flush(void) 752extern 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
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
diff --git a/firmware/export/ata.h b/firmware/export/ata.h
index 06de33a8f2..fb604a120d 100644
--- a/firmware/export/ata.h
+++ b/firmware/export/ata.h
@@ -20,6 +20,21 @@
20#define __ATA_H__ 20#define __ATA_H__
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23#include "config.h" /* for HAVE_MULTIVOLUME or not */
24
25/* FixMe: These macros are a bit nasty and perhaps misplaced here.
26 We'll get rid of them once decided on how to proceed with multivolume. */
27#ifdef HAVE_MULTIVOLUME
28#define IF_MV(x) x /* optional volume/drive parameter */
29#define IF_MV2(x,y) x,y /* same, for a list of arguments */
30#define IF_MV_NONVOID(x) x /* for prototype with sole volume parameter */
31#define NUM_VOLUMES 2
32#else /* empty definitions if no multi-volume */
33#define IF_MV(x)
34#define IF_MV2(x,y)
35#define IF_MV_NONVOID(x) void
36#define NUM_VOLUMES 1
37#endif
23 38
24/* 39/*
25 ata_spindown() time values: 40 ata_spindown() time values:
@@ -41,8 +56,8 @@ extern bool ata_disk_is_active(void);
41extern int ata_hard_reset(void); 56extern int ata_hard_reset(void);
42extern int ata_soft_reset(void); 57extern int ata_soft_reset(void);
43extern int ata_init(void); 58extern int ata_init(void);
44extern int ata_read_sectors(unsigned long start, int count, void* buf); 59extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
45extern int ata_write_sectors(unsigned long start, int count, const void* buf); 60extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
46extern void ata_delayed_write(unsigned long sector, const void* buf); 61extern void ata_delayed_write(unsigned long sector, const void* buf);
47extern void ata_flush(void); 62extern void ata_flush(void);
48extern void ata_spin(void); 63extern void ata_spin(void);
diff --git a/firmware/export/disk.h b/firmware/export/disk.h
index 7a9697aa13..70b73c6547 100644
--- a/firmware/export/disk.h
+++ b/firmware/export/disk.h
@@ -19,6 +19,8 @@
19#ifndef _DISK_H_ 19#ifndef _DISK_H_
20#define _DISK_H_ 20#define _DISK_H_
21 21
22#include "ata.h" /* for volume definitions */
23
22struct partinfo { 24struct partinfo {
23 unsigned long start; /* first sector (LBA) */ 25 unsigned long start; /* first sector (LBA) */
24 unsigned long size; /* number of sectors */ 26 unsigned long size; /* number of sectors */
@@ -30,7 +32,7 @@ struct partinfo {
30#define PARTITION_TYPE_FAT16 0x06 32#define PARTITION_TYPE_FAT16 0x06
31 33
32/* returns a pointer to an array of 8 partinfo structs */ 34/* returns a pointer to an array of 8 partinfo structs */
33struct partinfo* disk_init(void); 35struct partinfo* disk_init(IF_MV_NONVOID(int volume));
34struct partinfo* disk_partinfo(int partition); 36struct partinfo* disk_partinfo(int partition);
35 37
36#endif 38#endif
diff --git a/firmware/export/fat.h b/firmware/export/fat.h
index 6f9c9c5d11..7150d2b09f 100644
--- a/firmware/export/fat.h
+++ b/firmware/export/fat.h
@@ -21,6 +21,7 @@
21#define FAT_H 21#define FAT_H
22 22
23#include <stdbool.h> 23#include <stdbool.h>
24#include "ata.h" /* for volume definitions */
24 25
25#define SECTOR_SIZE 512 26#define SECTOR_SIZE 512
26 27
@@ -45,6 +46,7 @@ struct fat_direntry
45#define FAT_ATTR_VOLUME_ID 0x08 46#define FAT_ATTR_VOLUME_ID 0x08
46#define FAT_ATTR_DIRECTORY 0x10 47#define FAT_ATTR_DIRECTORY 0x10
47#define FAT_ATTR_ARCHIVE 0x20 48#define FAT_ATTR_ARCHIVE 0x20
49#define FAT_ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
48 50
49struct fat_file 51struct fat_file
50{ 52{
@@ -57,6 +59,9 @@ struct fat_file
57 unsigned int direntries; /* number of dir entries used by this file */ 59 unsigned int direntries; /* number of dir entries used by this file */
58 unsigned int dircluster; /* first cluster of dir */ 60 unsigned int dircluster; /* first cluster of dir */
59 bool eof; 61 bool eof;
62#ifdef HAVE_MULTIVOLUME
63 int volume; /* file resides on which volume */
64#endif
60}; 65};
61 66
62struct fat_dir 67struct fat_dir
@@ -69,14 +74,16 @@ struct fat_dir
69}; 74};
70 75
71 76
72extern int fat_mount(int startsector); 77extern void fat_init(void);
73extern void fat_size(unsigned int* size, unsigned int* free); 78extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector);
74extern void fat_recalc_free(void); 79extern void fat_size(IF_MV2(int volume,) unsigned int* size, unsigned int* free); // public for info
80extern void fat_recalc_free(IF_MV_NONVOID(int volume)); // public for debug info screen
75extern int fat_create_dir(const char* name, 81extern int fat_create_dir(const char* name,
76 struct fat_dir* newdir, 82 struct fat_dir* newdir,
77 struct fat_dir* dir); 83 struct fat_dir* dir);
78extern int fat_startsector(void); 84extern int fat_startsector(IF_MV_NONVOID(int volume)); // public for config sector
79extern int fat_open(unsigned int cluster, 85extern int fat_open(IF_MV2(int volume,)
86 unsigned int cluster,
80 struct fat_file* ent, 87 struct fat_file* ent,
81 const struct fat_dir* dir); 88 const struct fat_dir* dir);
82extern int fat_create_file(const char* name, 89extern int fat_create_file(const char* name,
@@ -93,9 +100,11 @@ extern int fat_rename(struct fat_file* file,
93 const unsigned char* newname, 100 const unsigned char* newname,
94 int size, int attr); 101 int size, int attr);
95 102
96extern int fat_opendir(struct fat_dir *ent, unsigned int currdir, 103extern int fat_opendir(IF_MV2(int volume,)
104 struct fat_dir *ent, unsigned int currdir,
97 const struct fat_dir *parent_dir); 105 const struct fat_dir *parent_dir);
98extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry); 106extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry);
99extern int fat_get_cluster_size(void); 107extern int fat_get_cluster_size(IF_MV_NONVOID(int volume));
108extern bool fat_ismounted(int volume);
100 109
101#endif 110#endif
diff --git a/firmware/include/dir.h b/firmware/include/dir.h
index 00c6664872..5c157e4696 100644
--- a/firmware/include/dir.h
+++ b/firmware/include/dir.h
@@ -30,6 +30,7 @@
30#define ATTR_VOLUME_ID 0x08 30#define ATTR_VOLUME_ID 0x08
31#define ATTR_DIRECTORY 0x10 31#define ATTR_DIRECTORY 0x10
32#define ATTR_ARCHIVE 0x20 32#define ATTR_ARCHIVE 0x20
33#define ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
33 34
34struct dirent { 35struct dirent {
35 unsigned char d_name[MAX_PATH]; 36 unsigned char d_name[MAX_PATH];
@@ -52,6 +53,9 @@ typedef struct {
52 struct fat_dir fatdir; 53 struct fat_dir fatdir;
53 struct fat_dir parent_dir; 54 struct fat_dir parent_dir;
54 struct dirent theent; 55 struct dirent theent;
56#ifdef HAVE_MULTIVOLUME
57 int volumecounter; /* running counter for faked volume entries */
58#endif
55} DIR; 59} DIR;
56 60
57#else /* SIMULATOR */ 61#else /* SIMULATOR */
diff --git a/firmware/test/fat/main.c b/firmware/test/fat/main.c
index 5607414bcb..5420199f92 100644
--- a/firmware/test/fat/main.c
+++ b/firmware/test/fat/main.c
@@ -677,7 +677,7 @@ int main(int argc, char *argv[])
677#endif 677#endif
678 ) { 678 ) {
679 DEBUGF("*** Mounting at block %ld\n",pinfo[i].start); 679 DEBUGF("*** Mounting at block %ld\n",pinfo[i].start);
680 rc = fat_mount(pinfo[i].start); 680 rc = fat_mount(IF_MV2(0,) IF_MV2(0,) pinfo[i].start);
681 if(rc) { 681 if(rc) {
682 DEBUGF("mount: %d",rc); 682 DEBUGF("mount: %d",rc);
683 return -1; 683 return -1;
@@ -686,7 +686,7 @@ int main(int argc, char *argv[])
686 } 686 }
687 } 687 }
688 if ( i==4 ) { 688 if ( i==4 ) {
689 if(fat_mount(0)) { 689 if(fat_mount(IF_MV2(0,) IF_MV2(0,) 0)) {
690 DEBUGF("No FAT32 partition!"); 690 DEBUGF("No FAT32 partition!");
691 return -1; 691 return -1;
692 } 692 }
diff --git a/firmware/test/i2c/main.c b/firmware/test/i2c/main.c
index 34d3dc68e2..4419dde171 100644
--- a/firmware/test/i2c/main.c
+++ b/firmware/test/i2c/main.c
@@ -1,639 +1,1278 @@
1/*************************************************************************** 1/***************************************************************************
2
2 * __________ __ ___. 3 * __________ __ ___.
4
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 5 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
6
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 7 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
8
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 9 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
10
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 11 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
12
7 * \/ \/ \/ \/ \/ 13 * \/ \/ \/ \/ \/
14
8 * $Id$ 15 * $Id$
16
9 * 17 *
18
10 * Copyright (C) 2002 by Linus Nielsen Feltzing 19 * Copyright (C) 2002 by Linus Nielsen Feltzing
20
11 * 21 *
22
12 * All files in this archive are subject to the GNU General Public License. 23 * All files in this archive are subject to the GNU General Public License.
24
13 * See the file COPYING in the source tree root for full license agreement. 25 * See the file COPYING in the source tree root for full license agreement.
26
14 * 27 *
28
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 29 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
30
16 * KIND, either express or implied. 31 * KIND, either express or implied.
32
17 * 33 *
34
18 ****************************************************************************/ 35 ****************************************************************************/
36
19#include <stdio.h> 37#include <stdio.h>
38
20#include <stdlib.h> 39#include <stdlib.h>
40
21#include <stdbool.h> 41#include <stdbool.h>
42
22#include <string.h> 43#include <string.h>
44
23#include "i2c.h" 45#include "i2c.h"
46
24#include "mas.h" 47#include "mas.h"
48
25#include "dac.h" 49#include "dac.h"
50
26#include "sh7034.h" 51#include "sh7034.h"
52
27#include "system.h" 53#include "system.h"
54
28#include "debug.h" 55#include "debug.h"
56
29#include "kernel.h" 57#include "kernel.h"
58
30#include "thread.h" 59#include "thread.h"
60
31#include "ata.h" 61#include "ata.h"
62
32#include "disk.h" 63#include "disk.h"
64
33#include "fat.h" 65#include "fat.h"
66
34#include "file.h" 67#include "file.h"
68
35#include "dir.h" 69#include "dir.h"
70
36#include "panic.h" 71#include "panic.h"
37 72
73
74
38#ifndef MIN 75#ifndef MIN
76
39#define MIN(a, b) (((a)<(b))?(a):(b)) 77#define MIN(a, b) (((a)<(b))?(a):(b))
78
40#endif 79#endif
41 80
81
82
42#define MPEG_PLAY 1 83#define MPEG_PLAY 1
84
43#define MPEG_STOP 2 85#define MPEG_STOP 2
86
44#define MPEG_PAUSE 3 87#define MPEG_PAUSE 3
88
45#define MPEG_RESUME 4 89#define MPEG_RESUME 4
90
46#define MPEG_NEED_DATA 100 91#define MPEG_NEED_DATA 100
47 92
93
94
48#define MP3_LOW_WATER 0x30000 95#define MP3_LOW_WATER 0x30000
96
49#define MP3_CHUNK_SIZE 0x20000 97#define MP3_CHUNK_SIZE 0x20000
50 98
99
100
51unsigned int bass_table[] = 101unsigned int bass_table[] =
102
52{ 103{
104
53 0, 105 0,
106
54 0x800, /* 1dB */ 107 0x800, /* 1dB */
108
55 0x10000, /* 2dB */ 109 0x10000, /* 2dB */
110
56 0x17c00, /* 3dB */ 111 0x17c00, /* 3dB */
112
57 0x1f800, /* 4dB */ 113 0x1f800, /* 4dB */
114
58 0x27000, /* 5dB */ 115 0x27000, /* 5dB */
116
59 0x2e400, /* 6dB */ 117 0x2e400, /* 6dB */
118
60 0x35800, /* 7dB */ 119 0x35800, /* 7dB */
120
61 0x3c000, /* 8dB */ 121 0x3c000, /* 8dB */
122
62 0x42800, /* 9dB */ 123 0x42800, /* 9dB */
124
63 0x48800, /* 10dB */ 125 0x48800, /* 10dB */
126
64 0x4e400, /* 11dB */ 127 0x4e400, /* 11dB */
128
65 0x53800, /* 12dB */ 129 0x53800, /* 12dB */
130
66 0x58800, /* 13dB */ 131 0x58800, /* 13dB */
132
67 0x5d400, /* 14dB */ 133 0x5d400, /* 14dB */
134
68 0x61800 /* 15dB */ 135 0x61800 /* 15dB */
136
69}; 137};
70 138
139
140
71unsigned int treble_table[] = 141unsigned int treble_table[] =
142
72{ 143{
144
73 0, 145 0,
146
74 0x5400, /* 1dB */ 147 0x5400, /* 1dB */
148
75 0xac00, /* 2dB */ 149 0xac00, /* 2dB */
150
76 0x10400, /* 3dB */ 151 0x10400, /* 3dB */
152
77 0x16000, /* 4dB */ 153 0x16000, /* 4dB */
154
78 0x1c000, /* 5dB */ 155 0x1c000, /* 5dB */
156
79 0x22400, /* 6dB */ 157 0x22400, /* 6dB */
158
80 0x28400, /* 7dB */ 159 0x28400, /* 7dB */
160
81 0x2ec00, /* 8dB */ 161 0x2ec00, /* 8dB */
162
82 0x35400, /* 9dB */ 163 0x35400, /* 9dB */
164
83 0x3c000, /* 10dB */ 165 0x3c000, /* 10dB */
166
84 0x42c00, /* 11dB */ 167 0x42c00, /* 11dB */
168
85 0x49c00, /* 12dB */ 169 0x49c00, /* 12dB */
170
86 0x51800, /* 13dB */ 171 0x51800, /* 13dB */
172
87 0x58400, /* 14dB */ 173 0x58400, /* 14dB */
174
88 0x5f800 /* 15dB */ 175 0x5f800 /* 15dB */
176
89}; 177};
90 178
179
180
91unsigned char fliptable[] = 181unsigned char fliptable[] =
182
92{ 183{
184
93 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 185 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
186
94 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 187 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
188
95 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 189 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
190
96 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 191 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
192
97 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 193 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
194
98 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 195 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
196
99 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 197 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
198
100 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 199 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
200
101 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 201 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
202
102 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 203 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
204
103 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 205 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
206
104 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 207 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
208
105 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 209 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
210
106 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 211 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
212
107 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 213 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
214
108 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 215 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
216
109 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 217 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
218
110 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 219 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
220
111 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 221 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
222
112 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 223 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
224
113 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 225 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
226
114 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 227 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
228
115 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 229 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
230
116 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 231 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
232
117 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 233 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
234
118 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 235 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
236
119 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 237 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
238
120 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 239 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
240
121 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 241 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
242
122 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 243 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
244
123 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 245 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
246
124 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff 247 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
248
125}; 249};
126 250
251
252
127extern unsigned int stack[]; 253extern unsigned int stack[];
254
128/* Place the MP3 data right after the stack */ 255/* Place the MP3 data right after the stack */
129 256
257
258
130#define MP3BUF_LEN 0x100000 /* 1 Mbyte */ 259#define MP3BUF_LEN 0x100000 /* 1 Mbyte */
131 260
261
262
132unsigned char *mp3buf = (unsigned char *)stack; 263unsigned char *mp3buf = (unsigned char *)stack;
133 264
265
266
134char *tracks[100]; 267char *tracks[100];
268
135int num_tracks; 269int num_tracks;
136 270
271
272
137int mp3buf_write; 273int mp3buf_write;
274
138int mp3buf_read; 275int mp3buf_read;
276
139int last_dma_chunk_size; 277int last_dma_chunk_size;
140 278
279
280
141bool dma_on; /* The DMA is active */ 281bool dma_on; /* The DMA is active */
282
142bool playing; /* We are playing an MP3 stream */ 283bool playing; /* We are playing an MP3 stream */
284
143bool filling; /* We are filling the buffer with data from disk */ 285bool filling; /* We are filling the buffer with data from disk */
144 286
287
288
145struct event_queue mpeg_queue; 289struct event_queue mpeg_queue;
146 290
291
292
147static void mas_poll_start(unsigned int interval_in_ms); 293static void mas_poll_start(unsigned int interval_in_ms);
294
148void mpeg_thread(void); 295void mpeg_thread(void);
149 296
297
298
150void reset_mp3_buffer(void) 299void reset_mp3_buffer(void)
300
151{ 301{
302
152 mp3buf_read = 0; 303 mp3buf_read = 0;
304
153 mp3buf_write = 0; 305 mp3buf_write = 0;
306
154} 307}
155 308
309
310
156void setup_sci0(void) 311void setup_sci0(void)
312
157{ 313{
314
158 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0 */ 315 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0 */
316
159 PBCR1 = (PBCR1 & 0x0cff) | 0x1200; 317 PBCR1 = (PBCR1 & 0x0cff) | 0x1200;
318
160 319
320
161 /* Set PB12 to output */ 321 /* Set PB12 to output */
322
162 PBIOR |= 0x1000; 323 PBIOR |= 0x1000;
163 324
325
326
164 /* Disable serial port */ 327 /* Disable serial port */
328
165 SCR0 = 0x00; 329 SCR0 = 0x00;
166 330
331
332
167 /* Synchronous, no prescale */ 333 /* Synchronous, no prescale */
334
168 SMR0 = 0x80; 335 SMR0 = 0x80;
169 336
337
338
170 /* Set baudrate 1Mbit/s */ 339 /* Set baudrate 1Mbit/s */
340
171 BRR0 = 0x03; 341 BRR0 = 0x03;
172 342
343
344
173 /* use SCK as serial clock output */ 345 /* use SCK as serial clock output */
346
174 SCR0 = 0x01; 347 SCR0 = 0x01;
175 348
349
350
176 /* Clear FER and PER */ 351 /* Clear FER and PER */
352
177 SSR0 &= 0xe7; 353 SSR0 &= 0xe7;
178 354
355
356
179 /* Set interrupt ITU2 and SCI0 priority to 0 */ 357 /* Set interrupt ITU2 and SCI0 priority to 0 */
358
180 IPRD &= 0x0ff0; 359 IPRD &= 0x0ff0;
181 360
361
362
182 /* set IRQ6 and IRQ7 to edge detect */ 363 /* set IRQ6 and IRQ7 to edge detect */
364
183 ICR |= 0x03; 365 ICR |= 0x03;
184 366
367
368
185 /* set PB15 and PB14 to inputs */ 369 /* set PB15 and PB14 to inputs */
370
186 PBIOR &= 0x7fff; 371 PBIOR &= 0x7fff;
372
187 PBIOR &= 0xbfff; 373 PBIOR &= 0xbfff;
188 374
375
376
189 /* set IRQ6 prio 8 and IRQ7 prio 0 */ 377 /* set IRQ6 prio 8 and IRQ7 prio 0 */
378
190 IPRB = ( IPRB & 0xff00 ) | 0x0080; 379 IPRB = ( IPRB & 0xff00 ) | 0x0080;
191 380
381
382
192 /* Enable End of DMA interrupt at prio 8 */ 383 /* Enable End of DMA interrupt at prio 8 */
384
193 IPRC = (IPRC & 0xf0ff) | 0x0800; 385 IPRC = (IPRC & 0xf0ff) | 0x0800;
386
194 387
388
195 /* Enable Tx (only!) */ 389 /* Enable Tx (only!) */
390
196 SCR0 |= 0x20; 391 SCR0 |= 0x20;
392
197} 393}
198 394
199 395
396
397
398
200void init_dma(void) 399void init_dma(void)
400
201{ 401{
402
202 SAR3 = (unsigned int) mp3buf + mp3buf_read; 403 SAR3 = (unsigned int) mp3buf + mp3buf_read;
404
203 DAR3 = 0x5FFFEC3; 405 DAR3 = 0x5FFFEC3;
406
204 CHCR3 &= ~0x0002; /* Clear interrupt */ 407 CHCR3 &= ~0x0002; /* Clear interrupt */
408
205 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */ 409 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
410
206 last_dma_chunk_size = MIN(65536, mp3buf_write - mp3buf_read); 411 last_dma_chunk_size = MIN(65536, mp3buf_write - mp3buf_read);
412
207 DTCR3 = last_dma_chunk_size & 0xffff; 413 DTCR3 = last_dma_chunk_size & 0xffff;
414
208 DMAOR = 0x0001; /* Enable DMA */ 415 DMAOR = 0x0001; /* Enable DMA */
416
209 CHCR3 |= 0x0001; /* Enable DMA IRQ */ 417 CHCR3 |= 0x0001; /* Enable DMA IRQ */
418
210} 419}
211 420
421
422
212void start_dma(void) 423void start_dma(void)
424
213{ 425{
426
214 SCR0 |= 0x80; 427 SCR0 |= 0x80;
428
215 dma_on = true; 429 dma_on = true;
430
216} 431}
217 432
433
434
218void stop_dma(void) 435void stop_dma(void)
436
219{ 437{
438
220 SCR0 &= 0x7f; 439 SCR0 &= 0x7f;
440
221 dma_on = false; 441 dma_on = false;
442
222} 443}
223 444
445
446
224void dma_tick(void) 447void dma_tick(void)
448
225{ 449{
450
226 /* Start DMA if it isn't running */ 451 /* Start DMA if it isn't running */
452
227 if(playing && !dma_on) 453 if(playing && !dma_on)
454
228 { 455 {
456
229 if(PBDR & 0x4000) 457 if(PBDR & 0x4000)
458
230 { 459 {
460
231 if(!(SCR0 & 0x80)) 461 if(!(SCR0 & 0x80))
462
232 start_dma(); 463 start_dma();
464
233 } 465 }
466
234 } 467 }
468
235} 469}
236 470
471
472
237void bitswap(unsigned char *data, int length) 473void bitswap(unsigned char *data, int length)
474
238{ 475{
476
239 int i; 477 int i;
478
240 for(i = 0;i < length;i++) 479 for(i = 0;i < length;i++)
480
241 { 481 {
482
242 data[i] = fliptable[data[i]]; 483 data[i] = fliptable[data[i]];
484
243 } 485 }
486
244} 487}
245 488
489
490
246int main(void) 491int main(void)
492
247{ 493{
494
248 char buf[40]; 495 char buf[40];
496
249 char str[32]; 497 char str[32];
498
250 int i=0; 499 int i=0;
500
251 DIR *d; 501 DIR *d;
502
252 struct dirent *dent; 503 struct dirent *dent;
504
253 char *tmp; 505 char *tmp;
506
254 int volume, bass, treble; 507 int volume, bass, treble;
508
255 unsigned short frame_count; 509 unsigned short frame_count;
510
256 511
512
257 /* Clear it all! */ 513 /* Clear it all! */
514
258 SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER); 515 SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER);
259 516
517
518
260 /* This enables the serial Rx interrupt, to be able to exit into the 519 /* This enables the serial Rx interrupt, to be able to exit into the
520
261 debugger when you hit CTRL-C */ 521 debugger when you hit CTRL-C */
522
262 SCR1 |= 0x40; 523 SCR1 |= 0x40;
524
263 SCR1 &= ~0x80; 525 SCR1 &= ~0x80;
264 526
527
528
265 IPRE |= 0xf000; /* Highest priority */ 529 IPRE |= 0xf000; /* Highest priority */
266 530
531
532
267 i2c_init(); 533 i2c_init();
268 534
535
536
269 dma_on = true; 537 dma_on = true;
538
270 539
540
271 kernel_init(); 541 kernel_init();
272 542
543
544
273 set_irq_level(0); 545 set_irq_level(0);
274 546
547
548
275 setup_sci0(); 549 setup_sci0();
276 550
551
552
277 i=mas_readmem(MAS_BANK_D1,0xff6,(unsigned long*)buf,2); 553 i=mas_readmem(MAS_BANK_D1,0xff6,(unsigned long*)buf,2);
554
278 if (i) { 555 if (i) {
556
279 debugf("Error - mas_readmem() returned %d\n", i); 557 debugf("Error - mas_readmem() returned %d\n", i);
558
280 while(1); 559 while(1);
560
281 } 561 }
282 562
563
564
283 i = buf[0] | buf[1] << 8; 565 i = buf[0] | buf[1] << 8;
566
284 debugf("MAS version: %x\n", i); 567 debugf("MAS version: %x\n", i);
568
285 i = buf[4] | buf[5] << 8; 569 i = buf[4] | buf[5] << 8;
570
286 debugf("MAS revision: %x\n", i); 571 debugf("MAS revision: %x\n", i);
287 572
573
574
288 i=mas_readmem(MAS_BANK_D1,0xff9,(unsigned long*)buf,7); 575 i=mas_readmem(MAS_BANK_D1,0xff9,(unsigned long*)buf,7);
576
289 if (i) { 577 if (i) {
578
290 debugf("Error - mas_readmem() returned %d\n", i); 579 debugf("Error - mas_readmem() returned %d\n", i);
580
291 while(1); 581 while(1);
582
292 } 583 }
293 584
585
586
294 for(i = 0;i < 7;i++) 587 for(i = 0;i < 7;i++)
588
295 { 589 {
590
296 str[i*2+1] = buf[i*4]; 591 str[i*2+1] = buf[i*4];
592
297 str[i*2] = buf[i*4+1]; 593 str[i*2] = buf[i*4+1];
594
298 } 595 }
596
299 str[i*2] = 0; 597 str[i*2] = 0;
598
300 debugf("Description: %s\n", str); 599 debugf("Description: %s\n", str);
301 600
601
602
302 i=mas_writereg(0x3b, 0x20); 603 i=mas_writereg(0x3b, 0x20);
604
303 if (i < 0) { 605 if (i < 0) {
606
304 debugf("Error - mas_writereg() returned %d\n", i); 607 debugf("Error - mas_writereg() returned %d\n", i);
608
305 while(1); 609 while(1);
610
306 } 611 }
307 612
613
614
308 i = mas_run(1); 615 i = mas_run(1);
616
309 if (i < 0) { 617 if (i < 0) {
618
310 debugf("Error - mas_run() returned %d\n", i); 619 debugf("Error - mas_run() returned %d\n", i);
620
311 while(1); 621 while(1);
622
312 } 623 }
313 624
625
626
314 i = ata_init(); 627 i = ata_init();
628
315 debugf("ata_init() returned %d\n", i); 629 debugf("ata_init() returned %d\n", i);
316 630
631
632
317 i = disk_init(); 633 i = disk_init();
634
318 debugf("disk_init() returned %d\n", i); 635 debugf("disk_init() returned %d\n", i);
319 636
637
638
320 debugf("part[0] starts at sector %d\n", part[0].start); 639 debugf("part[0] starts at sector %d\n", part[0].start);
640
321 641
322 i = fat_mount(part[0].start); 642
643 i = fat_mount(IF_MV2(0,) IF_MV2(0,) part[0].start);
644
323 debugf("fat_mount() returned %d\n", i); 645 debugf("fat_mount() returned %d\n", i);
324 646
647
648
325 num_tracks = 0; 649 num_tracks = 0;
650
326 if((d = opendir("/"))) 651 if((d = opendir("/")))
652
327 { 653 {
654
328 while((dent = readdir(d))) 655 while((dent = readdir(d)))
656
329 { 657 {
658
330 debugf("%s\n", dent->d_name); 659 debugf("%s\n", dent->d_name);
660
331 i = strlen(dent->d_name); 661 i = strlen(dent->d_name);
662
332 tmp = dent->d_name + i - 4; 663 tmp = dent->d_name + i - 4;
664
333 debugf("%s\n", tmp); 665 debugf("%s\n", tmp);
666
334 if(!stricmp(tmp, ".mp3")) 667 if(!stricmp(tmp, ".mp3"))
668
335 { 669 {
670
336 tmp = malloc(i+1); 671 tmp = malloc(i+1);
672
337 if(tmp) 673 if(tmp)
674
338 { 675 {
676
339 debugf("Adding track %s\n", dent->d_name); 677 debugf("Adding track %s\n", dent->d_name);
678
340 snprintf(tmp, i+1, "/%s", dent->d_name); 679 snprintf(tmp, i+1, "/%s", dent->d_name);
680
341 tracks[num_tracks++] = tmp; 681 tracks[num_tracks++] = tmp;
682
342 } 683 }
684
343 else 685 else
686
344 { 687 {
688
345 panicf("Out of memory\n"); 689 panicf("Out of memory\n");
690
346 } 691 }
692
347 } 693 }
694
348 } 695 }
696
349 closedir(d); 697 closedir(d);
698
350 } 699 }
351 700
701
702
352 debugf("Number of tracks: %d\n"); 703 debugf("Number of tracks: %d\n");
353 704
705
706
354 queue_init(&mpeg_queue); 707 queue_init(&mpeg_queue);
355 708
709
710
356 create_thread(mpeg_thread, stack - 0x2000, 0x4000); 711 create_thread(mpeg_thread, stack - 0x2000, 0x4000);
357 712
713
714
358 mas_poll_start(2); 715 mas_poll_start(2);
716
359 717
718
360 debugf("let's play...\n"); 719 debugf("let's play...\n");
361 720
721
722
362 queue_post(&mpeg_queue, MPEG_PLAY, 0); 723 queue_post(&mpeg_queue, MPEG_PLAY, 0);
363 724
725
726
364 volume = 0x2c; 727 volume = 0x2c;
365 728
729
730
366 if(dac_config(0x04) < 0) 731 if(dac_config(0x04) < 0)
732
367 debugf("DAC write failed\n"); 733 debugf("DAC write failed\n");
368 734
735
736
369 if(dac_volume(volume) < 0) 737 if(dac_volume(volume) < 0)
738
370 debugf("DAC write failed\n"); 739 debugf("DAC write failed\n");
371 740
741
742
372 bass = 12; 743 bass = 12;
744
373 treble = 8; 745 treble = 8;
746
374 747
748
375 mas_writereg(MAS_REG_KPRESCALE, 0xe9400); 749 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
750
376 mas_writereg(MAS_REG_KBASS, bass_table[bass]); 751 mas_writereg(MAS_REG_KBASS, bass_table[bass]);
752
377 mas_writereg(MAS_REG_KTREBLE, treble_table[treble]); 753 mas_writereg(MAS_REG_KTREBLE, treble_table[treble]);
754
378 755
756
379 while(1) 757 while(1)
758
380 { 759 {
760
381 sleep(HZ*4); 761 sleep(HZ*4);
762
382 } 763 }
764
383} 765}
384 766
767
768
385#pragma interrupt 769#pragma interrupt
770
386void IRQ6(void) 771void IRQ6(void)
772
387{ 773{
774
388 stop_dma(); 775 stop_dma();
776
389} 777}
390 778
779
780
391#pragma interrupt 781#pragma interrupt
782
392void DEI3(void) 783void DEI3(void)
784
393{ 785{
786
394 int unplayed_space_left; 787 int unplayed_space_left;
788
395 int space_until_end_of_buffer; 789 int space_until_end_of_buffer;
396 790
791
792
397 if(playing) 793 if(playing)
794
398 { 795 {
796
399 mp3buf_read += last_dma_chunk_size; 797 mp3buf_read += last_dma_chunk_size;
798
400 if(mp3buf_read >= MP3BUF_LEN) 799 if(mp3buf_read >= MP3BUF_LEN)
800
401 mp3buf_read = 0; 801 mp3buf_read = 0;
802
402 803
804
403 unplayed_space_left = mp3buf_write - mp3buf_read; 805 unplayed_space_left = mp3buf_write - mp3buf_read;
806
404 if(unplayed_space_left < 0) 807 if(unplayed_space_left < 0)
808
405 unplayed_space_left = MP3BUF_LEN + unplayed_space_left; 809 unplayed_space_left = MP3BUF_LEN + unplayed_space_left;
406 810
811
812
407 space_until_end_of_buffer = MP3BUF_LEN - mp3buf_read; 813 space_until_end_of_buffer = MP3BUF_LEN - mp3buf_read;
814
408 815
816
409 if(!filling && unplayed_space_left < MP3_LOW_WATER) 817 if(!filling && unplayed_space_left < MP3_LOW_WATER)
818
410 { 819 {
820
411 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 821 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
822
412 } 823 }
824
413 825
826
414 if(unplayed_space_left) 827 if(unplayed_space_left)
828
415 { 829 {
830
416 last_dma_chunk_size = MIN(65536, unplayed_space_left); 831 last_dma_chunk_size = MIN(65536, unplayed_space_left);
832
417 last_dma_chunk_size = MIN(last_dma_chunk_size, space_until_end_of_buffer); 833 last_dma_chunk_size = MIN(last_dma_chunk_size, space_until_end_of_buffer);
834
418 DTCR3 = last_dma_chunk_size & 0xffff; 835 DTCR3 = last_dma_chunk_size & 0xffff;
836
419 SAR3 = (unsigned int)mp3buf + mp3buf_read; 837 SAR3 = (unsigned int)mp3buf + mp3buf_read;
838
420 } 839 }
840
421 else 841 else
842
422 { 843 {
844
423 debugf("No more MP3 data. Stopping.\n"); 845 debugf("No more MP3 data. Stopping.\n");
846
424 CHCR3 = 0; /* Stop DMA interrupt */ 847 CHCR3 = 0; /* Stop DMA interrupt */
848
425 } 849 }
850
426 } 851 }
427 852
853
854
428 CHCR3 &= ~0x0002; /* Clear DMA interrupt */ 855 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
856
429} 857}
430 858
859
860
431static void mas_poll_start(unsigned int interval_in_ms) 861static void mas_poll_start(unsigned int interval_in_ms)
862
432{ 863{
864
433 unsigned int count; 865 unsigned int count;
434 866
867
868
435 count = FREQ / 1000 / 8 * interval_in_ms; 869 count = FREQ / 1000 / 8 * interval_in_ms;
436 870
871
872
437 if(count > 0xffff) 873 if(count > 0xffff)
874
438 { 875 {
876
439 panicf("Error! The MAS poll interval is too long (%d ms)\n", 877 panicf("Error! The MAS poll interval is too long (%d ms)\n",
878
440 interval_in_ms); 879 interval_in_ms);
880
441 return; 881 return;
882
442 } 883 }
884
443 885
886
444 /* We are using timer 1 */ 887 /* We are using timer 1 */
888
445 889
890
446 TSTR &= ~0x02; /* Stop the timer */ 891 TSTR &= ~0x02; /* Stop the timer */
892
447 TSNC &= ~0x02; /* No synchronization */ 893 TSNC &= ~0x02; /* No synchronization */
894
448 TMDR &= ~0x02; /* Operate normally */ 895 TMDR &= ~0x02; /* Operate normally */
449 896
897
898
450 TCNT1 = 0; /* Start counting at 0 */ 899 TCNT1 = 0; /* Start counting at 0 */
900
451 GRA1 = count; 901 GRA1 = count;
902
452 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */ 903 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
453 904
905
906
454 /* Enable interrupt on level 2 */ 907 /* Enable interrupt on level 2 */
908
455 IPRC = (IPRC & ~0x000f) | 0x0002; 909 IPRC = (IPRC & ~0x000f) | 0x0002;
910
456 911
912
457 TSR1 &= ~0x02; 913 TSR1 &= ~0x02;
914
458 TIER1 = 0xf9; /* Enable GRA match interrupt */ 915 TIER1 = 0xf9; /* Enable GRA match interrupt */
459 916
917
918
460 TSTR |= 0x02; /* Start timer 2 */ 919 TSTR |= 0x02; /* Start timer 2 */
920
461} 921}
462 922
923
924
463#pragma interrupt 925#pragma interrupt
926
464void IMIA1(void) 927void IMIA1(void)
928
465{ 929{
930
466 dma_tick(); 931 dma_tick();
932
467 TSR1 &= ~0x01; 933 TSR1 &= ~0x01;
934
468} 935}
469 936
937
938
470int track_index = 0; 939int track_index = 0;
940
471char *peek_next_track(int index) 941char *peek_next_track(int index)
942
472{ 943{
944
473 if(track_index < num_tracks) 945 if(track_index < num_tracks)
946
474 return tracks[track_index+index]; 947 return tracks[track_index+index];
948
475 else 949 else
950
476 return NULL; 951 return NULL;
952
477} 953}
478 954
955
956
479void next_track(void) 957void next_track(void)
958
480{ 959{
960
481 track_index++; 961 track_index++;
962
482} 963}
483 964
965
966
484int mpeg_file = -1; 967int mpeg_file = -1;
485 968
969
970
486int new_file(void) 971int new_file(void)
972
487{ 973{
974
488 char *trackname; 975 char *trackname;
489 976
977
978
490 trackname = peek_next_track(0); 979 trackname = peek_next_track(0);
491 980
981
982
492 debugf("playing %s\n", trackname); 983 debugf("playing %s\n", trackname);
984
493 mpeg_file = open(trackname, O_RDONLY); 985 mpeg_file = open(trackname, O_RDONLY);
986
494 if(mpeg_file < 0) 987 if(mpeg_file < 0)
988
495 { 989 {
990
496 debugf("Couldn't open file\n"); 991 debugf("Couldn't open file\n");
992
497 return -1; 993 return -1;
994
498 } 995 }
996
499 return 0; 997 return 0;
998
500} 999}
501 1000
1001
1002
502void mpeg_thread(void) 1003void mpeg_thread(void)
1004
503{ 1005{
1006
504 struct event ev; 1007 struct event ev;
1008
505 int len; 1009 int len;
1010
506 int free_space_left; 1011 int free_space_left;
1012
507 int amount_to_read; 1013 int amount_to_read;
1014
508 bool play_pending; 1015 bool play_pending;
509 1016
1017
1018
510 play_pending = false; 1019 play_pending = false;
1020
511 playing = false; 1021 playing = false;
512 1022
1023
1024
513 while(1) 1025 while(1)
1026
514 { 1027 {
1028
515 debugf("S\n"); 1029 debugf("S\n");
1030
516 queue_wait(&mpeg_queue, &ev); 1031 queue_wait(&mpeg_queue, &ev);
1032
517 switch(ev.id) 1033 switch(ev.id)
1034
518 { 1035 {
1036
519 case MPEG_PLAY: 1037 case MPEG_PLAY:
1038
520 /* Stop the current stream */ 1039 /* Stop the current stream */
1040
521 play_pending = false; 1041 play_pending = false;
1042
522 playing = false; 1043 playing = false;
1044
523 stop_dma(); 1045 stop_dma();
524 1046
1047
1048
525 reset_mp3_buffer(); 1049 reset_mp3_buffer();
526 1050
1051
1052
527 new_file(); 1053 new_file();
1054
528 1055
1056
529 /* Make it read more data */ 1057 /* Make it read more data */
1058
530 filling = true; 1059 filling = true;
1060
531 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 1061 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
532 1062
1063
1064
533 /* Tell the file loading code that we want to start playing 1065 /* Tell the file loading code that we want to start playing
1066
534 as soon as we have some data */ 1067 as soon as we have some data */
1068
535 play_pending = true; 1069 play_pending = true;
1070
536 break; 1071 break;
537 1072
1073
1074
538 case MPEG_STOP: 1075 case MPEG_STOP:
1076
539 /* Stop the current stream */ 1077 /* Stop the current stream */
1078
540 playing = false; 1079 playing = false;
1080
541 stop_dma(); 1081 stop_dma();
1082
542 break; 1083 break;
543 1084
1085
1086
544 case MPEG_PAUSE: 1087 case MPEG_PAUSE:
1088
545 /* Stop the current stream */ 1089 /* Stop the current stream */
1090
546 playing = false; 1091 playing = false;
1092
547 stop_dma(); 1093 stop_dma();
1094
548 break; 1095 break;
549 1096
1097
1098
550 case MPEG_RESUME: 1099 case MPEG_RESUME:
1100
551 /* Stop the current stream */ 1101 /* Stop the current stream */
1102
552 playing = true; 1103 playing = true;
1104
553 start_dma(); 1105 start_dma();
1106
554 break; 1107 break;
555 1108
1109
1110
556 case MPEG_NEED_DATA: 1111 case MPEG_NEED_DATA:
1112
557 free_space_left = mp3buf_read - mp3buf_write; 1113 free_space_left = mp3buf_read - mp3buf_write;
558 1114
1115
1116
559 /* We interpret 0 as "empty buffer" */ 1117 /* We interpret 0 as "empty buffer" */
1118
560 if(free_space_left <= 0) 1119 if(free_space_left <= 0)
1120
561 free_space_left = MP3BUF_LEN + free_space_left; 1121 free_space_left = MP3BUF_LEN + free_space_left;
562 1122
1123
1124
563 if(free_space_left <= MP3_CHUNK_SIZE) 1125 if(free_space_left <= MP3_CHUNK_SIZE)
1126
564 { 1127 {
1128
565 debugf("0\n"); 1129 debugf("0\n");
1130
566 ata_spindown(-1); 1131 ata_spindown(-1);
1132
567 filling = false; 1133 filling = false;
1134
568 break;; 1135 break;;
1136
569 } 1137 }
1138
570 1139
1140
571 amount_to_read = MIN(MP3_CHUNK_SIZE, free_space_left); 1141 amount_to_read = MIN(MP3_CHUNK_SIZE, free_space_left);
1142
572 amount_to_read = MIN(MP3BUF_LEN - mp3buf_write, amount_to_read); 1143 amount_to_read = MIN(MP3BUF_LEN - mp3buf_write, amount_to_read);
1144
573 1145
1146
574 /* Read in a few seconds worth of MP3 data. We don't want to 1147 /* Read in a few seconds worth of MP3 data. We don't want to
1148
575 read too large chunks because the bitswapping will take 1149 read too large chunks because the bitswapping will take
1150
576 too much time. We must keep the DMA happy and also give 1151 too much time. We must keep the DMA happy and also give
1152
577 the other threads a chance to run. */ 1153 the other threads a chance to run. */
1154
578 debugf("R\n"); 1155 debugf("R\n");
1156
579 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read); 1157 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read);
1158
580 if(len) 1159 if(len)
1160
581 { 1161 {
1162
582 debugf("B\n"); 1163 debugf("B\n");
1164
583 bitswap(mp3buf + mp3buf_write, len); 1165 bitswap(mp3buf + mp3buf_write, len);
1166
584 1167
1168
585 mp3buf_write += len; 1169 mp3buf_write += len;
1170
586 if(mp3buf_write >= MP3BUF_LEN) 1171 if(mp3buf_write >= MP3BUF_LEN)
1172
587 { 1173 {
1174
588 mp3buf_write = 0; 1175 mp3buf_write = 0;
1176
589 debugf("W\n"); 1177 debugf("W\n");
1178
590 } 1179 }
591 1180
1181
1182
592 /* Tell ourselves that we want more data */ 1183 /* Tell ourselves that we want more data */
1184
593 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 1185 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
594 1186
1187
1188
595 /* And while we're at it, see if we have startet playing 1189 /* And while we're at it, see if we have startet playing
1190
596 yet. If not, do it. */ 1191 yet. If not, do it. */
1192
597 if(play_pending) 1193 if(play_pending)
1194
598 { 1195 {
1196
599 play_pending = false; 1197 play_pending = false;
1198
600 playing = true; 1199 playing = true;
1200
601 1201
1202
602 init_dma(); 1203 init_dma();
1204
603 start_dma(); 1205 start_dma();
1206
604 } 1207 }
1208
605 } 1209 }
1210
606 else 1211 else
1212
607 { 1213 {
1214
608 close(mpeg_file); 1215 close(mpeg_file);
1216
609 1217
1218
610 /* Make sure that the write pointer is at a word 1219 /* Make sure that the write pointer is at a word
1220
611 boundary */ 1221 boundary */
1222
612 mp3buf_write &= 0xfffffffe; 1223 mp3buf_write &= 0xfffffffe;
613 1224
1225
1226
614 next_track(); 1227 next_track();
1228
615 if(new_file() < 0) 1229 if(new_file() < 0)
1230
616 { 1231 {
1232
617 /* No more data to play */ 1233 /* No more data to play */
1234
618 debugf("Finished playing\n"); 1235 debugf("Finished playing\n");
1236
619 playing = false; 1237 playing = false;
1238
620 ata_spindown(-1); 1239 ata_spindown(-1);
1240
621 filling = false; 1241 filling = false;
1242
622 } 1243 }
1244
623 else 1245 else
1246
624 { 1247 {
1248
625 /* Tell ourselves that we want more data */ 1249 /* Tell ourselves that we want more data */
1250
626 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 1251 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1252
627 } 1253 }
1254
628 } 1255 }
1256
629 break; 1257 break;
1258
630 } 1259 }
1260
631 } 1261 }
1262
632} 1263}
633 1264
1265
1266
634/* Newlib trap honeypot */ 1267/* Newlib trap honeypot */
1268
635void __trap34(void) 1269void __trap34(void)
1270
636{ 1271{
1272
637 debugf("newlib trap34\n"); 1273 debugf("newlib trap34\n");
1274
638 while(1); 1275 while(1);
1276
639} 1277}
1278
diff --git a/firmware/usb.c b/firmware/usb.c
index e27c003154..ab8e080c45 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -157,17 +157,38 @@ static void usb_slave_mode(bool on)
157 panicf("ata: %d",rc); 157 panicf("ata: %d",rc);
158 } 158 }
159 159
160 pinfo = disk_init(); 160 pinfo = disk_init(IF_MV(0));
161 if (!pinfo) 161 if (!pinfo)
162 panicf("disk: NULL"); 162 panicf("disk: NULL");
163 163
164 fat_init();
164 for ( i=0; i<4; i++ ) { 165 for ( i=0; i<4; i++ ) {
165 rc = fat_mount(pinfo[i].start); 166 rc = fat_mount(IF_MV2(0,) IF_MV2(0,) pinfo[i].start);
166 if (!rc) 167 if (!rc)
167 break; 168 break; /* only one partition gets mounted as of now */
168 } 169 }
169 if (i==4) 170 if (i==4)
170 panicf("mount: %d",rc); 171 panicf("mount: %d",rc);
172#ifdef HAVE_MULTIVOLUME
173 /* mount partition on the optional volume */
174#ifdef HAVE_MMC
175 if (mmc_detect()) /* for Ondio, only if card detected */
176#endif
177 {
178 pinfo = disk_init(1);
179 if (pinfo)
180 {
181 for ( i=0; i<4; i++ ) {
182 if (!fat_mount(1, 1, pinfo[i].start))
183 break; /* only one partition gets mounted as of now */
184 }
185
186 if ( i==4 ) {
187 rc = fat_mount(1, 1, 0);
188 }
189 }
190 }
191#endif /* #ifdef HAVE_MULTIVOLUME */
171 } 192 }
172} 193}
173 194