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