diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/dir.c | 24 | ||||
-rw-r--r-- | firmware/common/disk.c | 97 | ||||
-rw-r--r-- | firmware/common/file.c | 20 | ||||
-rw-r--r-- | firmware/drivers/fat.c | 4 | ||||
-rw-r--r-- | firmware/export/disk.h | 2 | ||||
-rw-r--r-- | firmware/include/dir.h | 2 | ||||
-rw-r--r-- | firmware/include/file.h | 1 |
7 files changed, 121 insertions, 29 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 4b4a5fa65d..aa55aeb9e9 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c | |||
@@ -67,6 +67,26 @@ static int strip_volume(const char* name, char* namecopy) | |||
67 | #endif /* #ifdef HAVE_MULTIVOLUME */ | 67 | #endif /* #ifdef HAVE_MULTIVOLUME */ |
68 | 68 | ||
69 | 69 | ||
70 | #ifdef HAVE_HOTSWAP | ||
71 | // release all dir handles on a given volume "by force", to avoid leaks | ||
72 | int release_dirs(int volume) | ||
73 | { | ||
74 | DIR* pdir = opendirs; | ||
75 | int dd; | ||
76 | int closed = 0; | ||
77 | for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++) | ||
78 | { | ||
79 | if (pdir->fatdir.file.volume == volume) | ||
80 | { | ||
81 | pdir->busy = false; /* mark as available, no further action */ | ||
82 | closed++; | ||
83 | } | ||
84 | } | ||
85 | return closed; /* return how many we did */ | ||
86 | } | ||
87 | #endif /* #ifdef HAVE_HOTSWAP */ | ||
88 | |||
89 | |||
70 | DIR* opendir(const char* name) | 90 | DIR* opendir(const char* name) |
71 | { | 91 | { |
72 | char namecopy[MAX_PATH]; | 92 | char namecopy[MAX_PATH]; |
@@ -154,6 +174,10 @@ struct dirent* readdir(DIR* dir) | |||
154 | { | 174 | { |
155 | struct fat_direntry entry; | 175 | struct fat_direntry entry; |
156 | struct dirent* theent = &(dir->theent); | 176 | struct dirent* theent = &(dir->theent); |
177 | |||
178 | if (!dir->busy) | ||
179 | return NULL; | ||
180 | |||
157 | #ifdef HAVE_MULTIVOLUME | 181 | #ifdef HAVE_MULTIVOLUME |
158 | /* Volumes (secondary file systems) get inserted into the root directory | 182 | /* Volumes (secondary file systems) get inserted into the root directory |
159 | of the first volume, since we have no separate top level. */ | 183 | of the first volume, since we have no separate top level. */ |
diff --git a/firmware/common/disk.c b/firmware/common/disk.c index 923dffbe46..fd6de55ddb 100644 --- a/firmware/common/disk.c +++ b/firmware/common/disk.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #ifdef HAVE_MMC | 23 | #ifdef HAVE_MMC |
24 | #include "ata_mmc.h" | 24 | #include "ata_mmc.h" |
25 | #endif | 25 | #endif |
26 | #include "file.h" /* for release_dirs() */ | ||
27 | #include "dir.h" /* for release_files() */ | ||
26 | #include "disk.h" | 28 | #include "disk.h" |
27 | 29 | ||
28 | /* Partition table entry layout: | 30 | /* Partition table entry layout: |
@@ -44,6 +46,7 @@ | |||
44 | ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) | 46 | ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) |
45 | 47 | ||
46 | static struct partinfo part[8]; /* space for 4 partitions on 2 drives */ | 48 | static struct partinfo part[8]; /* space for 4 partitions on 2 drives */ |
49 | static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */ | ||
47 | 50 | ||
48 | struct partinfo* disk_init(IF_MV_NONVOID(int drive)) | 51 | struct partinfo* disk_init(IF_MV_NONVOID(int drive)) |
49 | { | 52 | { |
@@ -95,46 +98,86 @@ struct partinfo* disk_partinfo(int partition) | |||
95 | 98 | ||
96 | int disk_mount_all(void) | 99 | int disk_mount_all(void) |
97 | { | 100 | { |
98 | struct partinfo* pinfo; | 101 | int mounted; |
99 | int i,j; | 102 | int i; |
100 | int mounted = 0; | 103 | |
101 | bool found; | 104 | fat_init(); /* reset all mounted partitions */ |
102 | int drives = 1; | 105 | for (i=0; i<NUM_VOLUMES; i++) |
106 | vol_drive[i] = -1; /* mark all as unassigned */ | ||
107 | |||
108 | mounted = disk_mount(0); | ||
103 | #ifdef HAVE_MMC | 109 | #ifdef HAVE_MMC |
104 | if (mmc_detect()) /* for Ondio, only if card detected */ | 110 | if (mmc_detect()) /* for Ondio, only if card detected */ |
105 | { | 111 | { |
106 | drives = 2; /* in such case we have two drives to try */ | 112 | mounted += disk_mount(1); /* try 2nd "drive", too */ |
107 | } | 113 | } |
108 | #endif | 114 | #endif |
109 | 115 | ||
110 | fat_init(); /* reset all mounted partitions */ | 116 | return mounted; |
111 | for (j=0; j<drives; j++) | 117 | } |
118 | |||
119 | static int get_free_volume(void) | ||
120 | { | ||
121 | int i; | ||
122 | for (i=0; i<NUM_VOLUMES; i++) | ||
123 | { | ||
124 | if (vol_drive[i] == -1) /* unassigned? */ | ||
125 | return i; | ||
126 | } | ||
127 | |||
128 | return -1; /* none found */ | ||
129 | } | ||
130 | |||
131 | int disk_mount(int drive) | ||
132 | { | ||
133 | int i; | ||
134 | int mounted = 0; /* reset partition-on-drive flag */ | ||
135 | int volume = get_free_volume(); | ||
136 | struct partinfo* pinfo = disk_init(IF_MV(drive)); | ||
137 | |||
138 | if (pinfo == NULL) | ||
139 | { | ||
140 | return 0; | ||
141 | } | ||
142 | for (i=0; volume != -1 && i<4; i++) | ||
112 | { | 143 | { |
113 | found = false; /* reset partition-on-drive flag */ | 144 | if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) pinfo[i].start)) |
114 | pinfo = disk_init(IF_MV(j)); | ||
115 | if (pinfo == NULL) | ||
116 | { | 145 | { |
117 | continue; | 146 | mounted++; |
147 | vol_drive[volume] = drive; /* remember the drive for this volume */ | ||
148 | volume = get_free_volume(); /* prepare next entry */ | ||
118 | } | 149 | } |
119 | for (i=0; mounted<NUM_VOLUMES && i<4; i++) | 150 | } |
151 | |||
152 | if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */ | ||
153 | { /* try "superfloppy" mode */ | ||
154 | DEBUGF("No partition found, trying to mount sector 0.\n"); | ||
155 | if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) 0)) | ||
120 | { | 156 | { |
121 | if (!fat_mount(IF_MV2(mounted,) IF_MV2(j,) pinfo[i].start)) | 157 | mounted = 1; |
122 | { | 158 | vol_drive[volume] = drive; /* remember the drive for this volume */ |
123 | mounted++; | ||
124 | found = true; /* at least one valid entry */ | ||
125 | } | ||
126 | } | 159 | } |
160 | } | ||
161 | return mounted; | ||
162 | } | ||
127 | 163 | ||
128 | if (!found && mounted<NUM_VOLUMES) /* none of the 4 entries worked? */ | 164 | #ifdef HAVE_HOTSWAP |
129 | { /* try "superfloppy" mode */ | 165 | int disk_unmount(int drive) |
130 | DEBUGF("No partition found, trying to mount sector 0.\n"); | 166 | { |
131 | if (!fat_mount(IF_MV2(mounted,) IF_MV2(j,) 0)) | 167 | int unmounted = 0; |
132 | { | 168 | int i; |
133 | mounted++; | 169 | for (i=0; i<NUM_VOLUMES; i++) |
134 | } | 170 | { |
171 | if (vol_drive[i] == drive) | ||
172 | { /* force releasing resources */ | ||
173 | vol_drive[i] = -1; /* mark unused */ | ||
174 | unmounted++; | ||
175 | release_files(i); | ||
176 | release_dirs(i); | ||
177 | fat_unmount(i, false); | ||
135 | } | 178 | } |
136 | } | 179 | } |
137 | 180 | ||
138 | return mounted; | 181 | return unmounted; |
139 | } | 182 | } |
140 | 183 | #endif /* #ifdef HAVE_HOTSWAP */ | |
diff --git a/firmware/common/file.c b/firmware/common/file.c index f04f787b45..795fc7df7e 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c | |||
@@ -660,3 +660,23 @@ off_t filesize(int fd) | |||
660 | 660 | ||
661 | return file->size; | 661 | return file->size; |
662 | } | 662 | } |
663 | |||
664 | |||
665 | #ifdef HAVE_HOTSWAP | ||
666 | // release all file handles on a given volume "by force", to avoid leaks | ||
667 | int release_files(int volume) | ||
668 | { | ||
669 | struct filedesc* pfile = openfiles; | ||
670 | int fd; | ||
671 | int closed = 0; | ||
672 | for ( fd=0; fd<MAX_OPEN_FILES; fd++, pfile++) | ||
673 | { | ||
674 | if (pfile->fatfile.volume == volume) | ||
675 | { | ||
676 | pfile->busy = false; /* mark as available, no further action */ | ||
677 | closed++; | ||
678 | } | ||
679 | } | ||
680 | return closed; /* return how many we did */ | ||
681 | } | ||
682 | #endif /* #ifdef HAVE_HOTSWAP */ | ||
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 3adca5e864..78aebd2e2b 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -482,7 +482,7 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector) | |||
482 | return 0; | 482 | return 0; |
483 | } | 483 | } |
484 | 484 | ||
485 | #ifdef HAVE_MULTIVOLUME | 485 | #ifdef HAVE_HOTSWAP |
486 | int fat_unmount(int volume, bool flush) | 486 | int fat_unmount(int volume, bool flush) |
487 | { | 487 | { |
488 | int rc; | 488 | int rc; |
@@ -511,7 +511,7 @@ int fat_unmount(int volume, bool flush) | |||
511 | fat_bpb->mounted = false; | 511 | fat_bpb->mounted = false; |
512 | return rc; | 512 | return rc; |
513 | } | 513 | } |
514 | #endif | 514 | #endif /* #ifdef HAVE_HOTSWAP */ |
515 | 515 | ||
516 | void fat_recalc_free(IF_MV_NONVOID(int volume)) | 516 | void fat_recalc_free(IF_MV_NONVOID(int volume)) |
517 | { | 517 | { |
diff --git a/firmware/export/disk.h b/firmware/export/disk.h index e8525d1f75..e10fe9e7dc 100644 --- a/firmware/export/disk.h +++ b/firmware/export/disk.h | |||
@@ -35,5 +35,7 @@ struct partinfo { | |||
35 | struct partinfo* disk_init(IF_MV_NONVOID(int volume)); | 35 | struct partinfo* disk_init(IF_MV_NONVOID(int volume)); |
36 | struct partinfo* disk_partinfo(int partition); | 36 | struct partinfo* disk_partinfo(int partition); |
37 | int disk_mount_all(void); /* returns the # of successful mounts */ | 37 | int disk_mount_all(void); /* returns the # of successful mounts */ |
38 | int disk_mount(int drive); | ||
39 | int disk_unmount(int drive); | ||
38 | 40 | ||
39 | #endif | 41 | #endif |
diff --git a/firmware/include/dir.h b/firmware/include/dir.h index 5c157e4696..8dcbb8e900 100644 --- a/firmware/include/dir.h +++ b/firmware/include/dir.h | |||
@@ -84,6 +84,8 @@ extern int rmdir(const char* name); | |||
84 | 84 | ||
85 | extern struct dirent* readdir(DIR* dir); | 85 | extern struct dirent* readdir(DIR* dir); |
86 | 86 | ||
87 | extern int release_dirs(int volume); | ||
88 | |||
87 | #endif /* DIRFUNCTIONS_DEFINED */ | 89 | #endif /* DIRFUNCTIONS_DEFINED */ |
88 | 90 | ||
89 | #endif | 91 | #endif |
diff --git a/firmware/include/file.h b/firmware/include/file.h index e76abaaa96..387c34cdd8 100644 --- a/firmware/include/file.h +++ b/firmware/include/file.h | |||
@@ -87,6 +87,7 @@ extern int remove(const char* pathname); | |||
87 | extern int rename(const char* path, const char* newname); | 87 | extern int rename(const char* path, const char* newname); |
88 | extern int ftruncate(int fd, off_t length); | 88 | extern int ftruncate(int fd, off_t length); |
89 | extern off_t filesize(int fd); | 89 | extern off_t filesize(int fd); |
90 | extern int release_files(int volume); | ||
90 | #endif /* SIMULATOR */ | 91 | #endif /* SIMULATOR */ |
91 | 92 | ||
92 | #endif | 93 | #endif |