29#include "module_debug.h"
33#define FATFS_FS_DRIVER_MOUNT_INFO_MAX ((int)(sizeof(fs_driver_mount_info) / sizeof(fs_driver_mount_info[0])))
36#define FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(varname) \
37 const char *modified_##varname;
39#define FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(varname, vol) \
43 int strlen_##varname; \
44 char *modified_scope_##varname; \
46 strlen_##varname = strlen(varname); \
47 modified_scope_##varname = __builtin_alloca(3 + strlen_##varname + 1); \
48 modified_scope_##varname[0] = '0' + (vol); \
49 modified_scope_##varname[1] = ':'; \
50 modified_scope_##varname[2] = '/'; \
51 memcpy((modified_scope_##varname) + 3, varname, strlen_##varname); \
52 modified_scope_##varname[3 + strlen_##varname] = '\x00'; \
53 modified_##varname = modified_scope_##varname; \
57 modified_##varname = varname; \
64static int _fs_lock_sema_id = -1;
67static int _fs_init_lock(
void)
71 M_DEBUG(
"%s\n", __func__);
77 if ((_fs_lock_sema_id = CreateSema(&sp)) < 0) {
85static void _fs_lock(
void)
89 WaitSema(_fs_lock_sema_id);
93static void _fs_unlock(
void)
97 SignalSema(_fs_lock_sema_id);
101static void fs_reset(
void)
103 M_DEBUG(
"%s\n", __func__);
105 if (_fs_lock_sema_id >= 0)
106 DeleteSema(_fs_lock_sema_id);
111static void fatfs_fs_driver_initialize_all_mount_info(
void)
114 for (i = 0; i < FATFS_FS_DRIVER_MOUNT_INFO_MAX; i += 1) {
115 memset(&(fs_driver_mount_info[i].fatfs), 0,
sizeof(fs_driver_mount_info[i].fatfs));
116 fs_driver_mount_info[i].mounted_bd = NULL;
120static int fatfs_fs_driver_find_mount_info_index_from_block_device(
const struct block_device *bd)
123 for (i = 0; i < FATFS_FS_DRIVER_MOUNT_INFO_MAX; i += 1) {
124 if (fs_driver_mount_info[i].mounted_bd == bd) {
131static int fatfs_fs_driver_find_mount_info_index_free(
void)
133 return fatfs_fs_driver_find_mount_info_index_from_block_device(NULL);
136struct block_device *fatfs_fs_driver_get_mounted_bd_from_index(
int mount_info_index)
139 if (mount_info_index > FATFS_FS_DRIVER_MOUNT_INFO_MAX) {
142 mounted_bd = fs_driver_mount_info[mount_info_index].mounted_bd;
146static FRESULT fatfs_fs_driver_mount_bd(
int mount_info_index,
struct block_device *bd)
151 M_DEBUG(
"%s\n", __func__);
153 mount_point[0] =
'0' + mount_info_index;
154 mount_point[1] =
':';
155 mount_point[2] =
'\x00';
157 fs_driver_mount_info[mount_info_index].mounted_bd = bd;
158 ret = f_mount(&(fs_driver_mount_info[mount_info_index].fatfs), mount_point, 1);
160 fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
165static void fatfs_fs_driver_unmount_bd(
int mount_info_index)
168 mount_point[0] =
'0' + mount_info_index;
169 mount_point[1] =
':';
170 mount_point[2] =
'\x00';
172 f_unmount(mount_point);
173 fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
176static void fatfs_fs_driver_stop_single_bd(
int mount_info_index)
180 mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(mount_info_index);
181 if (mounted_bd != NULL) {
182 fatfs_fs_driver_unmount_bd(mount_info_index);
183 mounted_bd->stop(mounted_bd);
187static void fatfs_fs_driver_stop_all_bd(
void)
190 for (i = 0; i < FATFS_FS_DRIVER_MOUNT_INFO_MAX; i += 1) {
191 fatfs_fs_driver_stop_single_bd(i);
197#define FS_MAX_TYPED_DRIVERS 8
198static iop_device_t fs_typed_drivers[FS_MAX_TYPED_DRIVERS];
199static char fs_typed_driver_names[FS_MAX_TYPED_DRIVERS][16];
200static int fs_typed_driver_count = 0;
207static void fs_ensure_typed_driver(
const char *path)
211 if (path == NULL || strcmp(path,
"mass") == 0)
214 for (i = 0; i < fs_typed_driver_count; i++) {
215 if (strcmp(fs_typed_driver_names[i], path) == 0)
219 if (fs_typed_driver_count >= FS_MAX_TYPED_DRIVERS) {
220 M_DEBUG(
"fs_ensure_typed_driver: pool exhausted, cannot register '%s'\n", path);
224 i = fs_typed_driver_count;
225 strncpy(fs_typed_driver_names[i], path,
sizeof(fs_typed_driver_names[i]) - 1);
226 fs_typed_driver_names[i][
sizeof(fs_typed_driver_names[i]) - 1] =
'\0';
228 fs_typed_drivers[i].name = fs_typed_driver_names[i];
230 fs_typed_drivers[i].
version = 2;
231 fs_typed_drivers[i].desc =
"FATFS driver";
232 fs_typed_drivers[i].ops = &fs_functarray;
234 DelDrv(fs_typed_driver_names[i]);
235 if (AddDrv(&fs_typed_drivers[i]) == 0) {
236 M_DEBUG(
"fs_ensure_typed_driver: registered '%s'\n", path);
237 fs_typed_driver_count++;
245static int fs_driver_resolve_volume(
const char *driver_name,
int unit)
249 if (strcmp(driver_name,
"mass") == 0) {
250 if (unit >= 0 && unit < FATFS_FS_DRIVER_MOUNT_INFO_MAX)
256 for (i = 0; i < FATFS_FS_DRIVER_MOUNT_INFO_MAX; i++) {
257 struct block_device *bd = fs_driver_mount_info[i].mounted_bd;
258 if (bd != NULL && bd->path != NULL && strcmp(bd->path, driver_name) == 0) {
269 int mount_info_index;
271 M_DEBUG(
"%s\n", __func__);
274 fs_ensure_typed_driver(bd->path);
277 mount_info_index = fatfs_fs_driver_find_mount_info_index_free();
278 if (mount_info_index != -1) {
279 M_DEBUG(
"connect_bd: trying to mount to index %d\n", mount_info_index);
280 if (fatfs_fs_driver_mount_bd(mount_info_index, bd) == FR_OK) {
286 M_DEBUG(
"connect_bd: failed to mount device\n");
292 int mount_info_index;
295 mount_info_index = fatfs_fs_driver_find_mount_info_index_from_block_device(bd);
296 if (mount_info_index != -1) {
297 fatfs_fs_driver_unmount_bd(mount_info_index);
305static FIL fil_structures[MAX_FILES];
308static DIR dir_structures[MAX_DIRS];
310static FIL *fs_find_free_fil_structure(
void)
314 M_DEBUG(
"%s\n", __func__);
316 for (i = 0; i < MAX_FILES; i++) {
317 if (fil_structures[i].obj.fs == NULL) {
318 return &fil_structures[i];
324static DIR *fs_find_free_dir_structure(
void)
328 M_DEBUG(
"%s\n", __func__);
330 for (i = 0; i < MAX_DIRS; i++) {
331 if (dir_structures[i].obj.fs == NULL) {
332 return &dir_structures[i];
339static int fs_open(
iop_file_t *fd,
const char *name,
int flags,
int mode)
341 M_DEBUG(
"%s: %s flags=%X mode=%X\n", __func__, name, flags, mode);
345 BYTE f_mode = FA_OPEN_EXISTING;
346 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
350 vol = fs_driver_resolve_volume(fd->device->name, fd->unit);
354 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, vol);
359 fd->privdata = fs_find_free_fil_structure();
360 if (fd->privdata == NULL) {
366 if (flags & O_RDONLY)
368 if (flags & O_WRONLY)
371 f_mode |= FA_OPEN_ALWAYS;
373 f_mode |= FA_CREATE_ALWAYS;
374 if (flags & O_APPEND)
375 f_mode |= FA_OPEN_APPEND;
377 ret = f_open(fd->privdata, modified_name, f_mode);
393 M_DEBUG(
"%s\n", __func__);
400 ret = f_close(fd->privdata);
410s64 fs_lseek64(
iop_file_t *fd, s64 offset,
int whence)
412 M_DEBUG(
"%s\n", __func__);
416 if (fd->privdata == NULL)
421 FIL *file = (FIL *)(fd->privdata);
423 FSIZE_t off = offset;
430 off = file->obj.objsize + offset;
434 res = f_lseek(file, off);
437 return (res == FR_OK) ? (s64)(file->fptr) : -res;
440static int fs_lseek(
iop_file_t *fd,
int offset,
int whence)
442 return fs_lseek64(fd, (s64)offset, whence);
446static int fs_write(
iop_file_t *fd,
void *buffer,
int size)
448 M_DEBUG(
"%s\n", __func__);
453 if (fd->privdata == NULL)
458 ret = f_write(fd->privdata, buffer, size, &bw);
461 return (ret == FR_OK) ? bw : 0;
465static int fs_read(
iop_file_t *fd,
void *buffer,
int size)
467 M_DEBUG(
"%s\n", __func__);
472 if (fd->privdata == NULL)
477 ret = f_read(fd->privdata, buffer, size, &br);
480 return (ret == FR_OK) ? br : 0;
484static int fs_remove(
iop_file_t *fd,
const char *name)
486 M_DEBUG(
"%s\n", __func__);
490 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
492 vol = fs_driver_resolve_volume(fd->device->name, fd->unit);
496 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, vol);
500 ret = f_unlink(modified_name);
507static int fs_mkdir(
iop_file_t *fd,
const char *name,
int mode)
509 M_DEBUG(
"%s\n", __func__);
513 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
517 vol = fs_driver_resolve_volume(fd->device->name, fd->unit);
521 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, vol);
525 ret = f_mkdir(modified_name);
532static int fs_dopen(
iop_file_t *fd,
const char *name)
534 M_DEBUG(
"%s: unit %d name %s\n", __func__, fd->unit, name);
538 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
540 vol = fs_driver_resolve_volume(fd->device->name, fd->unit);
544 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, vol);
549 fd->privdata = fs_find_free_dir_structure();
550 if (fd->privdata == NULL) {
555 ret = f_opendir(fd->privdata, modified_name);
569 M_DEBUG(
"%s\n", __func__);
576 ret = f_closedir(fd->privdata);
586static void fileInfoToStat(FILINFO *fno,
iox_stat_t *stat)
588 WORD fdate = fno->fdate;
589 WORD ftime = fno->ftime;
590 unsigned char stime[8];
594 stat->size = (
unsigned int)(fno->fsize);
595 stat->hisize = (
unsigned int)(fno->fsize>>32);
598 if (fno->fattrib & AM_DIR) {
603 if (!(fno->fattrib & AM_RDO)) {
614 stime[4] = (fdate & 31);
615 stime[5] = (fdate >> 5) & 15;
617 year = (fdate >> 9) + 1980;
618 stime[6] = year & 0xff;
619 stime[7] = (year >> 8) & 0xff;
621 stime[3] = (ftime >> 11);
622 stime[2] = (ftime >> 5) & 63;
623 stime[1] = (ftime << 1) & 31;
625 memcpy(stat->ctime, stime,
sizeof(stime));
626 memcpy(stat->atime, stime,
sizeof(stime));
627 memcpy(stat->mtime, stime,
sizeof(stime));
633 M_DEBUG(
"%s\n", __func__);
638 if (fd->privdata == NULL)
643 ret = f_readdir(fd->privdata, &fno);
645 if (ret == FR_OK && fno.fname[0]) {
646 strncpy(buffer->name, fno.fname, 255);
647 fileInfoToStat(&fno, &(buffer->stat));
660 M_DEBUG(
"%s: unit %d name %s\n", __func__, fd->unit, name);
665 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
667 vol = fs_driver_resolve_volume(fd->device->name, fd->unit);
673 const char *name_no_leading_slash = name;
674 while (*name_no_leading_slash ==
'/') {
675 name_no_leading_slash += 1;
677 if ((strcmp(name_no_leading_slash,
"") == 0) || (strcmp(name_no_leading_slash,
".") == 0)) {
678 if (fatfs_fs_driver_get_mounted_bd_from_index(vol) == NULL) {
682 memset(stat, 0,
sizeof(*stat));
688 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, vol);
692 ret = f_stat(modified_name, &fno);
695 fileInfoToStat(&fno, stat);
704static int get_frag_list(FIL *file,
void *rdata,
unsigned int rdatalen)
706 bd_fragment_t *f = (bd_fragment_t*)rdata;
707 int iMaxFragments = rdatalen /
sizeof(bd_fragment_t);
711 struct block_device* bd = fatfs_fs_driver_get_mounted_bd_from_index(file->obj.fs->pdrv);
713 DWORD iClusterStart = file->obj.sclust;
714 DWORD iClusterCurrent = iClusterStart;
717 DWORD iClusterNext = get_fat(&file->obj, iClusterCurrent);
718 if (iClusterNext != (iClusterCurrent + 1)) {
720 M_DEBUG(
"fragment: %uc - %uc + 1\n", iClusterStart, iClusterCurrent + 1);
721 if (iFragCount < iMaxFragments) {
722 u64 sector = clst2sect(file->obj.fs, iClusterStart) + bd->sectorOffset;
723 f[iFragCount].sector = sector;
724 f[iFragCount].count = clst2sect(file->obj.fs, iClusterCurrent) - clst2sect(file->obj.fs, iClusterStart) + file->obj.fs->csize;
725 DEBUG_U64_2XU32(sector);
726 M_DEBUG(
" - sectors: 0x%08x%08x count %u\n", sector_u32[1], sector_u32[0], f[iFragCount].
count);
729 iClusterStart = iClusterNext;
731 iClusterCurrent = iClusterNext;
732 }
while(iClusterCurrent < file->obj.fs->n_fatent);
738int fs_ioctl2(
iop_file_t *fd,
int cmd,
void *data,
unsigned int datalen,
void *rdata,
unsigned int rdatalen)
740 M_DEBUG(
"%s cmd=%d\n", __func__, cmd);
743 FIL *file = ((FIL *)(fd->privdata));
761 ret = file->obj.sclust;
765 if (rdata == NULL || rdatalen <
sizeof(u64))
772 struct block_device* bd = fatfs_fs_driver_get_mounted_bd_from_index(file->obj.fs->pdrv);
774 *(u64*)rdata = clst2sect(file->obj.fs, file->obj.sclust) + bd->sectorOffset;
778 struct block_device *mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(file->obj.fs->pdrv);
779 ret = (mounted_bd == NULL) ? -
ENXIO : *(int *)(mounted_bd->name);
783 strncpy(rdata, mounted_bd->name, rdatalen);
787 ret = get_frag_list(file, NULL, 0) == 1 ? 1 : 0;
790 ret = get_frag_list(file, rdata, rdatalen);
795 if (rdata == NULL || rdatalen <
sizeof(u32))
801 struct block_device* bd = fatfs_fs_driver_get_mounted_bd_from_index(file->obj.fs->pdrv);
806 *(u32*)rdata = bd->devNr;
820int fs_ioctl(
iop_file_t *fd,
int cmd,
void *data)
822 return fs_ioctl2(fd, cmd, data, 1024, NULL, 0);
825int fs_rename(
iop_file_t *fd,
const char *path,
const char *newpath)
827 M_DEBUG(
"%s\n", __func__);
831 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(path);
832 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(newpath);
834 vol = fs_driver_resolve_volume(fd->device->name, fd->unit);
838 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(path, vol);
839 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(newpath, vol);
842 if (strcmp(modified_path, modified_newpath) == 0) {
848 ret = f_rename(modified_path, modified_newpath);
854static int fs_devctl(
iop_file_t *fd,
const char *name,
int cmd,
void *arg,
unsigned int arglen,
void *buf,
unsigned int buflen)
869 fatfs_fs_driver_stop_all_bd();
874 int vol = fs_driver_resolve_volume(fd->device->name, fd->unit);
876 fatfs_fs_driver_stop_single_bd(vol);
891IOMANX_RETURN_VALUE_IMPL(0);
892IOMANX_RETURN_VALUE_IMPL(
EIO);
895 IOMANX_RETURN_VALUE(0),
896 IOMANX_RETURN_VALUE(0),
897 IOMANX_RETURN_VALUE(
EIO),
911 IOMANX_RETURN_VALUE(
EIO),
913 IOMANX_RETURN_VALUE(
EIO),
914 IOMANX_RETURN_VALUE(
EIO),
915 IOMANX_RETURN_VALUE(
EIO),
916 IOMANX_RETURN_VALUE(
EIO),
919 IOMANX_RETURN_VALUE(
EIO),
920 IOMANX_RETURN_VALUE(
EIO),
934 M_DEBUG(
"%s\n", __func__);
937 fatfs_fs_driver_initialize_all_mount_info();
938 fs_typed_driver_count = 0;
940 DelDrv(fs_driver.name);
941 return (AddDrv(&fs_driver) == 0 ? 0 : -1);
#define USBMASS_IOCTL_GET_CLUSTER
#define USBMASS_IOCTL_GET_DRIVERNAME
u32 count
start sector of fragmented bd/file
#define USBMASS_DEVCTL_STOP_ALL
#define USBMASS_DEVCTL_STOP_UNIT
#define USBMASS_IOCTL_RENAME
#define USBMASS_IOCTL_GET_DEVICE_NUMBER
#define USBMASS_IOCTL_GET_LBA
#define USBMASS_IOCTL_GET_FRAGLIST
#define USBMASS_IOCTL_CHECK_CHAIN