forked from len0rd/rockbox
prepared to mount multiple partitions into one logical file system (most useful for Ondio, internal memory + external MMC)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5514 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
ae45d970d8
commit
da84857631
18 changed files with 1330 additions and 329 deletions
32
apps/main.c
32
apps/main.c
|
|
@ -101,6 +101,9 @@ int main(void)
|
||||||
#ifdef CONFIG_TUNER
|
#ifdef CONFIG_TUNER
|
||||||
#include "radio.h"
|
#include "radio.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_MMC
|
||||||
|
#include "ata_mmc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
|
/*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
|
||||||
|
|
||||||
|
|
@ -236,7 +239,8 @@ void init(void)
|
||||||
|
|
||||||
usb_start_monitoring();
|
usb_start_monitoring();
|
||||||
|
|
||||||
pinfo = disk_init();
|
/* FixMe: the same kind of mounting happens in usb.c, share the code. */
|
||||||
|
pinfo = disk_init(IF_MV(0));
|
||||||
if (!pinfo)
|
if (!pinfo)
|
||||||
{
|
{
|
||||||
lcd_clear_display();
|
lcd_clear_display();
|
||||||
|
|
@ -252,14 +256,15 @@ void init(void)
|
||||||
system_reboot();
|
system_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fat_init();
|
||||||
for ( i=0; i<4; i++ ) {
|
for ( i=0; i<4; i++ ) {
|
||||||
if (!fat_mount(pinfo[i].start))
|
if (!fat_mount(IF_MV2(0,) IF_MV2(0,) pinfo[i].start))
|
||||||
break;
|
break; /* only one partition gets mounted as of now */
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( i==4 ) {
|
if ( i==4 ) {
|
||||||
DEBUGF("No partition found, trying to mount sector 0.\n");
|
DEBUGF("No partition found, trying to mount sector 0.\n");
|
||||||
rc = fat_mount(0);
|
rc = fat_mount(IF_MV2(0,) IF_MV2(0,) 0);
|
||||||
if(rc) {
|
if(rc) {
|
||||||
lcd_clear_display();
|
lcd_clear_display();
|
||||||
lcd_puts(0,0,"No FAT32");
|
lcd_puts(0,0,"No FAT32");
|
||||||
|
|
@ -272,7 +277,26 @@ void init(void)
|
||||||
/* The USB thread will panic if the drive still can't be mounted */
|
/* The USB thread will panic if the drive still can't be mounted */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
/* mount partition on the optional volume */
|
||||||
|
#ifdef HAVE_MMC
|
||||||
|
if (mmc_detect()) /* for Ondio, only if card detected */
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
pinfo = disk_init(1);
|
||||||
|
if (pinfo)
|
||||||
|
{
|
||||||
|
for ( i=0; i<4; i++ ) {
|
||||||
|
if (!fat_mount(1, 1, pinfo[i].start))
|
||||||
|
break; /* only one partition gets mounted as of now */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( i==4 ) {
|
||||||
|
rc = fat_mount(1, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* #ifdef HAVE_MULTIVOLUME */
|
||||||
settings_calc_config_sector();
|
settings_calc_config_sector();
|
||||||
settings_load(SETTINGS_ALL);
|
settings_load(SETTINGS_ALL);
|
||||||
settings_apply();
|
settings_apply();
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ bool show_info(void)
|
||||||
int state = 1;
|
int state = 1;
|
||||||
unsigned int size, free;
|
unsigned int size, free;
|
||||||
|
|
||||||
fat_size( &size, &free );
|
fat_size( IF_MV2(0,) &size, &free );
|
||||||
size /= 1024;
|
size /= 1024;
|
||||||
free /= 1024;
|
free /= 1024;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -513,8 +513,7 @@ static int load_config_buffer(int which)
|
||||||
if (which & SETTINGS_HD)
|
if (which & SETTINGS_HD)
|
||||||
{
|
{
|
||||||
if (config_sector != 0) {
|
if (config_sector != 0) {
|
||||||
ata_read_sectors( config_sector, 1, config_block);
|
ata_read_sectors(IF_MV2(0,) config_sector, 1, config_block);
|
||||||
|
|
||||||
/* calculate the checksum, check it and the header */
|
/* calculate the checksum, check it and the header */
|
||||||
chksum = calculate_config_checksum(config_block);
|
chksum = calculate_config_checksum(config_block);
|
||||||
|
|
||||||
|
|
@ -623,7 +622,7 @@ void settings_calc_config_sector(void)
|
||||||
int i, partition_start;
|
int i, partition_start;
|
||||||
int sector = 0;
|
int sector = 0;
|
||||||
|
|
||||||
if (fat_startsector() != 0) /* There is a partition table */
|
if (fat_startsector(IF_MV(0)) != 0) /* There is a partition table */
|
||||||
{
|
{
|
||||||
sector = 61;
|
sector = 61;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,13 @@ static int compare(const void* p1, const void* p2)
|
||||||
if (e1->attr & ATTR_DIRECTORY && e2->attr & ATTR_DIRECTORY)
|
if (e1->attr & ATTR_DIRECTORY && e2->attr & ATTR_DIRECTORY)
|
||||||
{ /* two directories */
|
{ /* two directories */
|
||||||
criteria = global_settings.sort_dir;
|
criteria = global_settings.sort_dir;
|
||||||
|
if (e1->attr & ATTR_VOLUME || e2->attr & ATTR_VOLUME)
|
||||||
|
{ /* a volume identifier is involved */
|
||||||
|
if (e1->attr & ATTR_VOLUME && e2->attr & ATTR_VOLUME)
|
||||||
|
criteria = 0; /* two volumes: sort alphabetically */
|
||||||
|
else /* only one is a volume: volume first */
|
||||||
|
return (e2->attr & ATTR_VOLUME) - (e1->attr & ATTR_VOLUME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!(e1->attr & ATTR_DIRECTORY) && !(e2->attr & ATTR_DIRECTORY))
|
else if (!(e1->attr & ATTR_DIRECTORY) && !(e2->attr & ATTR_DIRECTORY))
|
||||||
{ /* two files */
|
{ /* two files */
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ struct filetype {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* using attribute bits not used by FAT (FAT uses lower 6) */
|
/* using attribute bits not used by FAT (FAT uses lower 7) */
|
||||||
|
|
||||||
#define TREE_ATTR_THUMBNAIL 0x0080 /* corresponding .talk file exists */
|
#define TREE_ATTR_THUMBNAIL 0x0080 /* corresponding .talk file exists */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,48 @@
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "atoi.h"
|
||||||
|
|
||||||
#define MAX_OPEN_DIRS 8
|
#define MAX_OPEN_DIRS 8
|
||||||
|
|
||||||
static DIR opendirs[MAX_OPEN_DIRS];
|
static DIR opendirs[MAX_OPEN_DIRS];
|
||||||
|
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
|
||||||
|
/* how to name volumes, first char must be outside of legal file names,
|
||||||
|
a number gets appended to enumerate, if applicable */
|
||||||
|
#ifdef HAVE_MMC
|
||||||
|
static const char* vol_names = ":MMC";
|
||||||
|
#else
|
||||||
|
static const char* vol_names = ":HD";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* returns on which volume this is, and copies the reduced name
|
||||||
|
(sortof a preprocessor for volume-decorated pathnames) */
|
||||||
|
static int strip_volume(const char* name, char* namecopy)
|
||||||
|
{
|
||||||
|
int volume = 0;
|
||||||
|
|
||||||
|
if (name[1] == vol_names[0] ) /* a colon identifies our volumes */
|
||||||
|
{
|
||||||
|
const char* temp;
|
||||||
|
temp = name + 1 + strlen(vol_names); /* behind special name */
|
||||||
|
volume = atoi(temp); /* number is following */
|
||||||
|
temp = strchr(temp, '/'); /* search for slash behind */
|
||||||
|
if (temp != NULL)
|
||||||
|
name = temp; /* use the part behind the volume */
|
||||||
|
else
|
||||||
|
name = "/"; /* else this must be the root dir */
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(namecopy, name, MAX_PATH);
|
||||||
|
namecopy[MAX_PATH-1] = '\0';
|
||||||
|
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
#endif /* #ifdef HAVE_MULTIVOLUME */
|
||||||
|
|
||||||
|
|
||||||
DIR* opendir(const char* name)
|
DIR* opendir(const char* name)
|
||||||
{
|
{
|
||||||
char namecopy[MAX_PATH];
|
char namecopy[MAX_PATH];
|
||||||
|
|
@ -35,6 +72,9 @@ DIR* opendir(const char* name)
|
||||||
char* end;
|
char* end;
|
||||||
struct fat_direntry entry;
|
struct fat_direntry entry;
|
||||||
int dd;
|
int dd;
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
int volume;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* find a free dir descriptor */
|
/* find a free dir descriptor */
|
||||||
for ( dd=0; dd<MAX_OPEN_DIRS; dd++ )
|
for ( dd=0; dd<MAX_OPEN_DIRS; dd++ )
|
||||||
|
|
@ -55,15 +95,21 @@ DIR* opendir(const char* name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fat_opendir(&(opendirs[dd].fatdir), 0, NULL) < 0 ) {
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
/* try to extract a heading volume name, if present */
|
||||||
|
volume = strip_volume(name, namecopy);
|
||||||
|
opendirs[dd].volumecounter = 0;
|
||||||
|
#else
|
||||||
|
strncpy(namecopy,name,sizeof(namecopy)); /* just copy */
|
||||||
|
namecopy[sizeof(namecopy)-1] = '\0';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( fat_opendir(IF_MV2(volume,) &(opendirs[dd].fatdir), 0, NULL) < 0 ) {
|
||||||
DEBUGF("Failed opening root dir\n");
|
DEBUGF("Failed opening root dir\n");
|
||||||
opendirs[dd].busy = false;
|
opendirs[dd].busy = false;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(namecopy,name,sizeof(namecopy));
|
|
||||||
namecopy[sizeof(namecopy)-1] = 0;
|
|
||||||
|
|
||||||
for ( part = strtok_r(namecopy, "/", &end); part;
|
for ( part = strtok_r(namecopy, "/", &end); part;
|
||||||
part = strtok_r(NULL, "/", &end)) {
|
part = strtok_r(NULL, "/", &end)) {
|
||||||
/* scan dir for name */
|
/* scan dir for name */
|
||||||
|
|
@ -76,7 +122,8 @@ DIR* opendir(const char* name)
|
||||||
if ( (entry.attr & FAT_ATTR_DIRECTORY) &&
|
if ( (entry.attr & FAT_ATTR_DIRECTORY) &&
|
||||||
(!strcasecmp(part, entry.name)) ) {
|
(!strcasecmp(part, entry.name)) ) {
|
||||||
opendirs[dd].parent_dir = opendirs[dd].fatdir;
|
opendirs[dd].parent_dir = opendirs[dd].fatdir;
|
||||||
if ( fat_opendir(&(opendirs[dd].fatdir),
|
if ( fat_opendir(IF_MV2(volume,)
|
||||||
|
&(opendirs[dd].fatdir),
|
||||||
entry.firstcluster,
|
entry.firstcluster,
|
||||||
&(opendirs[dd].parent_dir)) < 0 ) {
|
&(opendirs[dd].parent_dir)) < 0 ) {
|
||||||
DEBUGF("Failed opening dir '%s' (%d)\n",
|
DEBUGF("Failed opening dir '%s' (%d)\n",
|
||||||
|
|
@ -84,6 +131,9 @@ DIR* opendir(const char* name)
|
||||||
opendirs[dd].busy = false;
|
opendirs[dd].busy = false;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
opendirs[dd].volumecounter = -1; /* n.a. to subdirs */
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +152,28 @@ struct dirent* readdir(DIR* dir)
|
||||||
{
|
{
|
||||||
struct fat_direntry entry;
|
struct fat_direntry entry;
|
||||||
struct dirent* theent = &(dir->theent);
|
struct dirent* theent = &(dir->theent);
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
/* Volumes (secondary file systems) get inserted into the root directory
|
||||||
|
of the first volume, since we have no separate top level. */
|
||||||
|
if (dir->volumecounter >= 0 /* on a root dir */
|
||||||
|
&& dir->volumecounter < NUM_VOLUMES /* in range */
|
||||||
|
&& dir->fatdir.file.volume == 0) /* at volume 0 */
|
||||||
|
{ /* fake special directories, which don't really exist, but
|
||||||
|
will get redirected upon opendir() */
|
||||||
|
while (++dir->volumecounter < NUM_VOLUMES)
|
||||||
|
{
|
||||||
|
if (fat_ismounted(dir->volumecounter))
|
||||||
|
{
|
||||||
|
memset(theent, 0, sizeof(*theent));
|
||||||
|
theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
|
||||||
|
snprintf(theent->d_name, sizeof(theent->d_name),
|
||||||
|
"%s%d", vol_names, dir->volumecounter);
|
||||||
|
return theent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* normal directory entry fetching follows here */
|
||||||
if (fat_getnext(&(dir->fatdir),&entry) < 0)
|
if (fat_getnext(&(dir->fatdir),&entry) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,22 @@
|
||||||
|
|
||||||
static struct partinfo part[8];
|
static struct partinfo part[8];
|
||||||
|
|
||||||
struct partinfo* disk_init(void)
|
struct partinfo* disk_init(IF_MV_NONVOID(int drive))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned char sector[512];
|
unsigned char sector[512];
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
/* For each drive, start at a different position, in order not to destroy
|
||||||
|
the first entry of drive 0.
|
||||||
|
That one is needed to calculate config sector position. */
|
||||||
|
struct partinfo* pinfo = &part[drive*4];
|
||||||
|
if ((size_t)drive >= sizeof(part)/sizeof(*part)/4)
|
||||||
|
return NULL; /* out of space in table */
|
||||||
|
#else
|
||||||
|
struct partinfo* pinfo = part;
|
||||||
|
#endif
|
||||||
|
|
||||||
ata_read_sectors(0,1,§or);
|
ata_read_sectors(IF_MV2(drive,) 0,1,§or);
|
||||||
|
|
||||||
/* check that the boot sector is initialized */
|
/* check that the boot sector is initialized */
|
||||||
if ( (sector[510] != 0x55) ||
|
if ( (sector[510] != 0x55) ||
|
||||||
|
|
@ -58,20 +68,20 @@ struct partinfo* disk_init(void)
|
||||||
/* parse partitions */
|
/* parse partitions */
|
||||||
for ( i=0; i<4; i++ ) {
|
for ( i=0; i<4; i++ ) {
|
||||||
unsigned char* ptr = sector + 0x1be + 16*i;
|
unsigned char* ptr = sector + 0x1be + 16*i;
|
||||||
part[i].type = ptr[4];
|
pinfo[i].type = ptr[4];
|
||||||
part[i].start = BYTES2INT32(ptr, 8);
|
pinfo[i].start = BYTES2INT32(ptr, 8);
|
||||||
part[i].size = BYTES2INT32(ptr, 12);
|
pinfo[i].size = BYTES2INT32(ptr, 12);
|
||||||
|
|
||||||
DEBUGF("Part%d: Type %02x, start: %08x size: %08x\n",
|
DEBUGF("Part%d: Type %02x, start: %08x size: %08x\n",
|
||||||
i,part[i].type,part[i].start,part[i].size);
|
i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
|
||||||
|
|
||||||
/* extended? */
|
/* extended? */
|
||||||
if ( part[i].type == 5 ) {
|
if ( pinfo[i].type == 5 ) {
|
||||||
/* not handled yet */
|
/* not handled yet */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return part;
|
return pinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct partinfo* disk_partinfo(int partition)
|
struct partinfo* disk_partinfo(int partition)
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,8 @@ int open(const char* pathname, int flags)
|
||||||
/* scan dir for name */
|
/* scan dir for name */
|
||||||
while ((entry = readdir(dir))) {
|
while ((entry = readdir(dir))) {
|
||||||
if ( !strcasecmp(name, entry->d_name) ) {
|
if ( !strcasecmp(name, entry->d_name) ) {
|
||||||
fat_open(entry->startcluster,
|
fat_open(IF_MV2(dir->fatdir.file.volume,)
|
||||||
|
entry->startcluster,
|
||||||
&(file->fatfile),
|
&(file->fatfile),
|
||||||
&(dir->fatdir));
|
&(dir->fatdir));
|
||||||
file->size = file->trunc ? 0 : entry->size;
|
file->size = file->trunc ? 0 : entry->size;
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,8 @@ static void copy_read_sectors(unsigned char* buf, int wordcount)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int ata_read_sectors(unsigned long start,
|
int ata_read_sectors(IF_MV((int drive,))
|
||||||
|
unsigned long start,
|
||||||
int incount,
|
int incount,
|
||||||
void* inbuf)
|
void* inbuf)
|
||||||
{
|
{
|
||||||
|
|
@ -576,7 +577,8 @@ static void copy_write_sectors(const unsigned char* buf, int wordcount)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int ata_write_sectors(unsigned long start,
|
int ata_write_sectors(IF_MV((int drive,))
|
||||||
|
unsigned long start,
|
||||||
int count,
|
int count,
|
||||||
const void* buf)
|
const void* buf)
|
||||||
{
|
{
|
||||||
|
|
@ -669,6 +671,8 @@ int ata_write_sectors(unsigned long start,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* schedule a single sector write, executed with the the next spinup
|
||||||
|
(volume 0 only, used for config sector) */
|
||||||
extern void ata_delayed_write(unsigned long sector, const void* buf)
|
extern void ata_delayed_write(unsigned long sector, const void* buf)
|
||||||
{
|
{
|
||||||
memcpy(delayed_sector, buf, SECTOR_SIZE);
|
memcpy(delayed_sector, buf, SECTOR_SIZE);
|
||||||
|
|
@ -676,12 +680,13 @@ extern void ata_delayed_write(unsigned long sector, const void* buf)
|
||||||
delayed_write = true;
|
delayed_write = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* write the delayed sector to volume 0 */
|
||||||
extern void ata_flush(void)
|
extern void ata_flush(void)
|
||||||
{
|
{
|
||||||
if ( delayed_write ) {
|
if ( delayed_write ) {
|
||||||
DEBUGF("ata_flush()\n");
|
DEBUGF("ata_flush()\n");
|
||||||
delayed_write = false;
|
delayed_write = false;
|
||||||
ata_write_sectors(delayed_sector_num, 1, delayed_sector);
|
ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -608,7 +608,11 @@ static int send_single_sector(const unsigned char *buf, int timeout)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ata_read_sectors(unsigned long start,
|
int ata_read_sectors(
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
int drive,
|
||||||
|
#endif
|
||||||
|
unsigned long start,
|
||||||
int incount,
|
int incount,
|
||||||
void* inbuf)
|
void* inbuf)
|
||||||
{
|
{
|
||||||
|
|
@ -617,8 +621,11 @@ int ata_read_sectors(unsigned long start,
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
unsigned char response;
|
unsigned char response;
|
||||||
void *inbuf_prev = NULL;
|
void *inbuf_prev = NULL;
|
||||||
tCardInfo *card = &card_info[current_card];
|
tCardInfo *card;
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
current_card = drive;
|
||||||
|
#endif
|
||||||
|
card = &card_info[current_card];
|
||||||
addr = start * SECTOR_SIZE;
|
addr = start * SECTOR_SIZE;
|
||||||
|
|
||||||
mutex_lock(&mmc_mutex);
|
mutex_lock(&mmc_mutex);
|
||||||
|
|
@ -663,7 +670,11 @@ int ata_read_sectors(unsigned long start,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ata_write_sectors(unsigned long start,
|
int ata_write_sectors(
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
int drive,
|
||||||
|
#endif
|
||||||
|
unsigned long start,
|
||||||
int count,
|
int count,
|
||||||
const void* buf)
|
const void* buf)
|
||||||
{
|
{
|
||||||
|
|
@ -671,7 +682,11 @@ int ata_write_sectors(unsigned long start,
|
||||||
int i;
|
int i;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
unsigned char response;
|
unsigned char response;
|
||||||
tCardInfo *card = &card_info[current_card];
|
tCardInfo *card;
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
current_card = drive;
|
||||||
|
#endif
|
||||||
|
card = &card_info[current_card];
|
||||||
|
|
||||||
if (start == 0)
|
if (start == 0)
|
||||||
panicf("Writing on sector 0\n");
|
panicf("Writing on sector 0\n");
|
||||||
|
|
@ -733,12 +748,13 @@ extern void ata_delayed_write(unsigned long sector, const void* buf)
|
||||||
delayed_write = true;
|
delayed_write = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* write the delayed sector to volume 0 */
|
||||||
extern void ata_flush(void)
|
extern void ata_flush(void)
|
||||||
{
|
{
|
||||||
if ( delayed_write ) {
|
if ( delayed_write ) {
|
||||||
DEBUGF("ata_flush()\n");
|
DEBUGF("ata_flush()\n");
|
||||||
delayed_write = false;
|
delayed_write = false;
|
||||||
ata_write_sectors(delayed_sector_num, 1, delayed_sector);
|
ata_write_sectors(IF_MV2(0,) delayed_sector_num, 1, delayed_sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -20,6 +20,21 @@
|
||||||
#define __ATA_H__
|
#define __ATA_H__
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "config.h" /* for HAVE_MULTIVOLUME or not */
|
||||||
|
|
||||||
|
/* FixMe: These macros are a bit nasty and perhaps misplaced here.
|
||||||
|
We'll get rid of them once decided on how to proceed with multivolume. */
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
#define IF_MV(x) x /* optional volume/drive parameter */
|
||||||
|
#define IF_MV2(x,y) x,y /* same, for a list of arguments */
|
||||||
|
#define IF_MV_NONVOID(x) x /* for prototype with sole volume parameter */
|
||||||
|
#define NUM_VOLUMES 2
|
||||||
|
#else /* empty definitions if no multi-volume */
|
||||||
|
#define IF_MV(x)
|
||||||
|
#define IF_MV2(x,y)
|
||||||
|
#define IF_MV_NONVOID(x) void
|
||||||
|
#define NUM_VOLUMES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ata_spindown() time values:
|
ata_spindown() time values:
|
||||||
|
|
@ -41,8 +56,8 @@ extern bool ata_disk_is_active(void);
|
||||||
extern int ata_hard_reset(void);
|
extern int ata_hard_reset(void);
|
||||||
extern int ata_soft_reset(void);
|
extern int ata_soft_reset(void);
|
||||||
extern int ata_init(void);
|
extern int ata_init(void);
|
||||||
extern int ata_read_sectors(unsigned long start, int count, void* buf);
|
extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
|
||||||
extern int ata_write_sectors(unsigned long start, int count, const void* buf);
|
extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
|
||||||
extern void ata_delayed_write(unsigned long sector, const void* buf);
|
extern void ata_delayed_write(unsigned long sector, const void* buf);
|
||||||
extern void ata_flush(void);
|
extern void ata_flush(void);
|
||||||
extern void ata_spin(void);
|
extern void ata_spin(void);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
#ifndef _DISK_H_
|
#ifndef _DISK_H_
|
||||||
#define _DISK_H_
|
#define _DISK_H_
|
||||||
|
|
||||||
|
#include "ata.h" /* for volume definitions */
|
||||||
|
|
||||||
struct partinfo {
|
struct partinfo {
|
||||||
unsigned long start; /* first sector (LBA) */
|
unsigned long start; /* first sector (LBA) */
|
||||||
unsigned long size; /* number of sectors */
|
unsigned long size; /* number of sectors */
|
||||||
|
|
@ -30,7 +32,7 @@ struct partinfo {
|
||||||
#define PARTITION_TYPE_FAT16 0x06
|
#define PARTITION_TYPE_FAT16 0x06
|
||||||
|
|
||||||
/* returns a pointer to an array of 8 partinfo structs */
|
/* returns a pointer to an array of 8 partinfo structs */
|
||||||
struct partinfo* disk_init(void);
|
struct partinfo* disk_init(IF_MV_NONVOID(int volume));
|
||||||
struct partinfo* disk_partinfo(int partition);
|
struct partinfo* disk_partinfo(int partition);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#define FAT_H
|
#define FAT_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "ata.h" /* for volume definitions */
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
|
|
||||||
|
|
@ -45,6 +46,7 @@ struct fat_direntry
|
||||||
#define FAT_ATTR_VOLUME_ID 0x08
|
#define FAT_ATTR_VOLUME_ID 0x08
|
||||||
#define FAT_ATTR_DIRECTORY 0x10
|
#define FAT_ATTR_DIRECTORY 0x10
|
||||||
#define FAT_ATTR_ARCHIVE 0x20
|
#define FAT_ATTR_ARCHIVE 0x20
|
||||||
|
#define FAT_ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
|
||||||
|
|
||||||
struct fat_file
|
struct fat_file
|
||||||
{
|
{
|
||||||
|
|
@ -57,6 +59,9 @@ struct fat_file
|
||||||
unsigned int direntries; /* number of dir entries used by this file */
|
unsigned int direntries; /* number of dir entries used by this file */
|
||||||
unsigned int dircluster; /* first cluster of dir */
|
unsigned int dircluster; /* first cluster of dir */
|
||||||
bool eof;
|
bool eof;
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
int volume; /* file resides on which volume */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fat_dir
|
struct fat_dir
|
||||||
|
|
@ -69,14 +74,16 @@ struct fat_dir
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern int fat_mount(int startsector);
|
extern void fat_init(void);
|
||||||
extern void fat_size(unsigned int* size, unsigned int* free);
|
extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector);
|
||||||
extern void fat_recalc_free(void);
|
extern void fat_size(IF_MV2(int volume,) unsigned int* size, unsigned int* free); // public for info
|
||||||
|
extern void fat_recalc_free(IF_MV_NONVOID(int volume)); // public for debug info screen
|
||||||
extern int fat_create_dir(const char* name,
|
extern int fat_create_dir(const char* name,
|
||||||
struct fat_dir* newdir,
|
struct fat_dir* newdir,
|
||||||
struct fat_dir* dir);
|
struct fat_dir* dir);
|
||||||
extern int fat_startsector(void);
|
extern int fat_startsector(IF_MV_NONVOID(int volume)); // public for config sector
|
||||||
extern int fat_open(unsigned int cluster,
|
extern int fat_open(IF_MV2(int volume,)
|
||||||
|
unsigned int cluster,
|
||||||
struct fat_file* ent,
|
struct fat_file* ent,
|
||||||
const struct fat_dir* dir);
|
const struct fat_dir* dir);
|
||||||
extern int fat_create_file(const char* name,
|
extern int fat_create_file(const char* name,
|
||||||
|
|
@ -93,9 +100,11 @@ extern int fat_rename(struct fat_file* file,
|
||||||
const unsigned char* newname,
|
const unsigned char* newname,
|
||||||
int size, int attr);
|
int size, int attr);
|
||||||
|
|
||||||
extern int fat_opendir(struct fat_dir *ent, unsigned int currdir,
|
extern int fat_opendir(IF_MV2(int volume,)
|
||||||
|
struct fat_dir *ent, unsigned int currdir,
|
||||||
const struct fat_dir *parent_dir);
|
const struct fat_dir *parent_dir);
|
||||||
extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry);
|
extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry);
|
||||||
extern int fat_get_cluster_size(void);
|
extern int fat_get_cluster_size(IF_MV_NONVOID(int volume));
|
||||||
|
extern bool fat_ismounted(int volume);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#define ATTR_VOLUME_ID 0x08
|
#define ATTR_VOLUME_ID 0x08
|
||||||
#define ATTR_DIRECTORY 0x10
|
#define ATTR_DIRECTORY 0x10
|
||||||
#define ATTR_ARCHIVE 0x20
|
#define ATTR_ARCHIVE 0x20
|
||||||
|
#define ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
|
||||||
|
|
||||||
struct dirent {
|
struct dirent {
|
||||||
unsigned char d_name[MAX_PATH];
|
unsigned char d_name[MAX_PATH];
|
||||||
|
|
@ -52,6 +53,9 @@ typedef struct {
|
||||||
struct fat_dir fatdir;
|
struct fat_dir fatdir;
|
||||||
struct fat_dir parent_dir;
|
struct fat_dir parent_dir;
|
||||||
struct dirent theent;
|
struct dirent theent;
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
int volumecounter; /* running counter for faked volume entries */
|
||||||
|
#endif
|
||||||
} DIR;
|
} DIR;
|
||||||
|
|
||||||
#else /* SIMULATOR */
|
#else /* SIMULATOR */
|
||||||
|
|
|
||||||
|
|
@ -677,7 +677,7 @@ int main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
DEBUGF("*** Mounting at block %ld\n",pinfo[i].start);
|
DEBUGF("*** Mounting at block %ld\n",pinfo[i].start);
|
||||||
rc = fat_mount(pinfo[i].start);
|
rc = fat_mount(IF_MV2(0,) IF_MV2(0,) pinfo[i].start);
|
||||||
if(rc) {
|
if(rc) {
|
||||||
DEBUGF("mount: %d",rc);
|
DEBUGF("mount: %d",rc);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -686,7 +686,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( i==4 ) {
|
if ( i==4 ) {
|
||||||
if(fat_mount(0)) {
|
if(fat_mount(IF_MV2(0,) IF_MV2(0,) 0)) {
|
||||||
DEBUGF("No FAT32 partition!");
|
DEBUGF("No FAT32 partition!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -157,17 +157,38 @@ static void usb_slave_mode(bool on)
|
||||||
panicf("ata: %d",rc);
|
panicf("ata: %d",rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
pinfo = disk_init();
|
pinfo = disk_init(IF_MV(0));
|
||||||
if (!pinfo)
|
if (!pinfo)
|
||||||
panicf("disk: NULL");
|
panicf("disk: NULL");
|
||||||
|
|
||||||
|
fat_init();
|
||||||
for ( i=0; i<4; i++ ) {
|
for ( i=0; i<4; i++ ) {
|
||||||
rc = fat_mount(pinfo[i].start);
|
rc = fat_mount(IF_MV2(0,) IF_MV2(0,) pinfo[i].start);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
break;
|
break; /* only one partition gets mounted as of now */
|
||||||
}
|
}
|
||||||
if (i==4)
|
if (i==4)
|
||||||
panicf("mount: %d",rc);
|
panicf("mount: %d",rc);
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
/* mount partition on the optional volume */
|
||||||
|
#ifdef HAVE_MMC
|
||||||
|
if (mmc_detect()) /* for Ondio, only if card detected */
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
pinfo = disk_init(1);
|
||||||
|
if (pinfo)
|
||||||
|
{
|
||||||
|
for ( i=0; i<4; i++ ) {
|
||||||
|
if (!fat_mount(1, 1, pinfo[i].start))
|
||||||
|
break; /* only one partition gets mounted as of now */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( i==4 ) {
|
||||||
|
rc = fat_mount(1, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* #ifdef HAVE_MULTIVOLUME */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue