PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
fs_driver.c
1/*
2 * fat_driver.c - USB Mass storage driver for PS2
3 *
4 * (C) 2004, Marek Olejnik (ole00@post.cz)
5 * (C) 2004 Hermes (support for sector sizes from 512 to 4096 bytes)
6 * (C) 2004 raipsu (fs_dopen, fs_dclose, fs_dread, fs_getstat implementation)
7 *
8 * FAT filesystem layer
9 *
10 * See the file LICENSE included with this distribution for licensing terms.
11 */
12//---------------------------------------------------------------------------
13#include <errno.h>
14#include <iomanX.h>
15#include <stdio.h>
16
17#include <sysclib.h>
18#include <sysmem.h>
19#include <thbase.h>
20#include <thsemap.h>
21
22#include <bdm.h>
23
24#include <usbhdfsd-common.h>
25
26#include "fs_driver.h"
27
28//#define DEBUG //comment out this line when not debugging
29#include "module_debug.h"
30
31fatfs_fs_driver_mount_info fs_driver_mount_info[FF_VOLUMES];
32
33#define FATFS_FS_DRIVER_MOUNT_INFO_MAX ((int)(sizeof(fs_driver_mount_info) / sizeof(fs_driver_mount_info[0])))
34
35// Macros for defining the modified path on stack.
36#define FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(varname) \
37 const char *modified_##varname;
38
39#define FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(varname, fd) \
40 { \
41 if ((fd)->unit != 0) \
42 { \
43 int strlen_##varname; \
44 char *modified_scope_##varname; \
45 \
46 strlen_##varname = strlen(varname); \
47 modified_scope_##varname = __builtin_alloca(3 + strlen_##varname + 1); \
48 modified_scope_##varname[0] = '0' + (fd)->unit; \
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; \
54 } \
55 else \
56 { \
57 modified_##varname = varname; \
58 } \
59 }
60
61
62
63//---------------------------------------------------------------------------
64static int _fs_lock_sema_id = -1;
65
66//---------------------------------------------------------------------------
67static int _fs_init_lock(void)
68{
69 iop_sema_t sp;
70
71 M_DEBUG("%s\n", __func__);
72
73 sp.initial = 1;
74 sp.max = 1;
75 sp.option = 0;
76 sp.attr = 0;
77 if ((_fs_lock_sema_id = CreateSema(&sp)) < 0) {
78 return (-1);
79 }
80
81 return (0);
82}
83
84//---------------------------------------------------------------------------
85static void _fs_lock(void)
86{
87 //M_DEBUG("%s\n", __func__);
88
89 WaitSema(_fs_lock_sema_id);
90}
91
92//---------------------------------------------------------------------------
93static void _fs_unlock(void)
94{
95 //M_DEBUG("%s\n", __func__);
96
97 SignalSema(_fs_lock_sema_id);
98}
99
100//---------------------------------------------------------------------------
101static void fs_reset(void)
102{
103 M_DEBUG("%s\n", __func__);
104
105 if (_fs_lock_sema_id >= 0)
106 DeleteSema(_fs_lock_sema_id);
107
108 _fs_init_lock();
109}
110
111static void fatfs_fs_driver_initialize_all_mount_info(void)
112{
113 int i;
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;
117 }
118}
119
120static int fatfs_fs_driver_find_mount_info_index_from_block_device(const struct block_device *bd)
121{
122 int i;
123 for (i = 0; i < FATFS_FS_DRIVER_MOUNT_INFO_MAX; i += 1) {
124 if (fs_driver_mount_info[i].mounted_bd == bd) {
125 return i;
126 }
127 }
128 return -1;
129}
130
131static int fatfs_fs_driver_find_mount_info_index_free(void)
132{
133 return fatfs_fs_driver_find_mount_info_index_from_block_device(NULL);
134}
135
136struct block_device *fatfs_fs_driver_get_mounted_bd_from_index(int mount_info_index)
137{
138 struct block_device *mounted_bd;
139 if (mount_info_index > FATFS_FS_DRIVER_MOUNT_INFO_MAX) {
140 return NULL;
141 }
142 mounted_bd = fs_driver_mount_info[mount_info_index].mounted_bd;
143 return mounted_bd;
144}
145
146static FRESULT fatfs_fs_driver_mount_bd(int mount_info_index, struct block_device *bd)
147{
148 int ret;
149 char mount_point[3];
150
151 M_DEBUG("%s\n", __func__);
152
153 mount_point[0] = '0' + mount_info_index;
154 mount_point[1] = ':';
155 mount_point[2] = '\x00';
156
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);
159 if (ret != FR_OK) {
160 fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
161 }
162 return ret;
163}
164
165static void fatfs_fs_driver_unmount_bd(int mount_info_index)
166{
167 char mount_point[3];
168 mount_point[0] = '0' + mount_info_index;
169 mount_point[1] = ':';
170 mount_point[2] = '\x00';
171
172 f_unmount(mount_point);
173 fs_driver_mount_info[mount_info_index].mounted_bd = NULL;
174}
175
176static void fatfs_fs_driver_stop_single_bd(int mount_info_index)
177{
178 struct block_device *mounted_bd;
179
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);
184 }
185}
186
187static void fatfs_fs_driver_stop_all_bd(void)
188{
189 int i;
190 for (i = 0; i < FATFS_FS_DRIVER_MOUNT_INFO_MAX; i += 1) {
191 fatfs_fs_driver_stop_single_bd(i);
192 }
193}
194
195int connect_bd(struct block_device *bd)
196{
197 int mount_info_index;
198
199 M_DEBUG("%s\n", __func__);
200
201 _fs_lock();
202 mount_info_index = fatfs_fs_driver_find_mount_info_index_free();
203 if (mount_info_index != -1) {
204 M_DEBUG("connect_bd: trying to mount to index %d\n", mount_info_index);
205 if (fatfs_fs_driver_mount_bd(mount_info_index, bd) == FR_OK) {
206 _fs_unlock();
207 return 0;
208 }
209 }
210 _fs_unlock();
211 M_DEBUG("connect_bd: failed to mount device\n");
212 return -1;
213}
214
215void disconnect_bd(struct block_device *bd)
216{
217 int mount_info_index;
218
219 _fs_lock();
220 mount_info_index = fatfs_fs_driver_find_mount_info_index_from_block_device(bd);
221 if (mount_info_index != -1) {
222 fatfs_fs_driver_unmount_bd(mount_info_index);
223 }
224 _fs_unlock();
225}
226
227//---------------------------------------------------------------------------
228
229#define MAX_FILES 128
230static FIL fil_structures[MAX_FILES];
231
232#define MAX_DIRS 16
233static DIR dir_structures[MAX_DIRS];
234
235static FIL *fs_find_free_fil_structure(void)
236{
237 int i;
238
239 M_DEBUG("%s\n", __func__);
240
241 for (i = 0; i < MAX_FILES; i++) {
242 if (fil_structures[i].obj.fs == NULL) {
243 return &fil_structures[i];
244 }
245 }
246 return NULL;
247}
248
249static DIR *fs_find_free_dir_structure(void)
250{
251 int i;
252
253 M_DEBUG("%s\n", __func__);
254
255 for (i = 0; i < MAX_DIRS; i++) {
256 if (dir_structures[i].obj.fs == NULL) {
257 return &dir_structures[i];
258 }
259 }
260 return NULL;
261}
262
263//---------------------------------------------------------------------------
264static int fs_open(iop_file_t *fd, const char *name, int flags, int mode)
265{
266 M_DEBUG("%s: %s flags=%X mode=%X\n", __func__, name, flags, mode);
267
268 int ret;
269 BYTE f_mode = FA_OPEN_EXISTING;
270 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
271
272 (void)mode;
273
274 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, fd);
275
276 _fs_lock();
277
278 // check if the slot is free
279 fd->privdata = fs_find_free_fil_structure();
280 if (fd->privdata == NULL) {
281 _fs_unlock();
282 return -EMFILE;
283 }
284
285 // translate mode
286 if (flags & O_RDONLY)
287 f_mode |= FA_READ;
288 if (flags & O_WRONLY)
289 f_mode |= FA_WRITE;
290 if (flags & O_CREAT)
291 f_mode |= FA_OPEN_ALWAYS;
292 if (flags & O_TRUNC)
293 f_mode |= FA_CREATE_ALWAYS;
294 if (flags & O_APPEND)
295 f_mode |= FA_OPEN_APPEND;
296
297 ret = f_open(fd->privdata, modified_name, f_mode);
298
299 if (ret != FR_OK) {
300 fd->privdata = NULL;
301 ret = -ret;
302 } else {
303 ret = 1;
304 }
305
306 _fs_unlock();
307 return ret;
308}
309
310//---------------------------------------------------------------------------
311static int fs_close(iop_file_t *fd)
312{
313 M_DEBUG("%s\n", __func__);
314
315 int ret = FR_OK;
316
317 _fs_lock();
318
319 if (fd->privdata) {
320 ret = f_close(fd->privdata);
321 fd->privdata = NULL;
322 }
323
324 _fs_unlock();
325 return -ret;
326}
327
328//---------------------------------------------------------------------------
329
330s64 fs_lseek64(iop_file_t *fd, s64 offset, int whence)
331{
332 M_DEBUG("%s\n", __func__);
333
334 int res;
335
336 if (fd->privdata == NULL)
337 return -ENOENT;
338
339 _fs_lock();
340
341 FIL *file = (FIL *)(fd->privdata);
342
343 FSIZE_t off = offset;
344
345 switch (whence) {
346 case SEEK_CUR:
347 off += file->fptr;
348 break;
349 case SEEK_END:
350 off = file->obj.objsize + offset;
351 break;
352 }
353
354 res = f_lseek(file, off);
355
356 _fs_unlock();
357 return (res == FR_OK) ? (s64)(file->fptr) : -res;
358}
359
360static int fs_lseek(iop_file_t *fd, int offset, int whence)
361{
362 return fs_lseek64(fd, (s64)offset, whence);
363}
364
365//---------------------------------------------------------------------------
366static int fs_write(iop_file_t *fd, void *buffer, int size)
367{
368 M_DEBUG("%s\n", __func__);
369
370 int ret;
371 UINT bw;
372
373 if (fd->privdata == NULL)
374 return -ENOENT;
375
376 _fs_lock();
377
378 ret = f_write(fd->privdata, buffer, size, &bw);
379
380 _fs_unlock();
381 return (ret == FR_OK) ? bw : 0;
382}
383
384//---------------------------------------------------------------------------
385static int fs_read(iop_file_t *fd, void *buffer, int size)
386{
387 M_DEBUG("%s\n", __func__);
388
389 int ret;
390 UINT br;
391
392 if (fd->privdata == NULL)
393 return -ENOENT;
394
395 _fs_lock();
396
397 ret = f_read(fd->privdata, buffer, size, &br);
398
399 _fs_unlock();
400 return (ret == FR_OK) ? br : 0;
401}
402
403//---------------------------------------------------------------------------
404static int fs_remove(iop_file_t *fd, const char *name)
405{
406 M_DEBUG("%s\n", __func__);
407
408 int ret;
409 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
410
411 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, fd);
412
413 _fs_lock();
414
415 ret = f_unlink(modified_name);
416
417 _fs_unlock();
418 return -ret;
419}
420
421//---------------------------------------------------------------------------
422static int fs_mkdir(iop_file_t *fd, const char *name, int mode)
423{
424 M_DEBUG("%s\n", __func__);
425
426 int ret;
427 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
428
429 (void)mode;
430
431 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, fd);
432
433 _fs_lock();
434
435 ret = f_mkdir(modified_name);
436
437 _fs_unlock();
438 return -ret;
439}
440
441//---------------------------------------------------------------------------
442static int fs_dopen(iop_file_t *fd, const char *name)
443{
444 M_DEBUG("%s: unit %d name %s\n", __func__, fd->unit, name);
445
446 int ret;
447 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
448
449 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, fd);
450
451 _fs_lock();
452
453 // check if the slot is free
454 fd->privdata = fs_find_free_dir_structure();
455 if (fd->privdata == NULL) {
456 _fs_unlock();
457 return -EMFILE;
458 }
459
460 ret = f_opendir(fd->privdata, modified_name);
461
462 if (ret != FR_OK) {
463 fd->privdata = NULL;
464 ret = -ret;
465 }
466
467 _fs_unlock();
468 return ret;
469}
470
471//---------------------------------------------------------------------------
472static int fs_dclose(iop_file_t *fd)
473{
474 M_DEBUG("%s\n", __func__);
475
476 int ret = ENOENT;
477
478 _fs_lock();
479
480 if (fd->privdata) {
481 ret = f_closedir(fd->privdata);
482 fd->privdata = NULL;
483 }
484
485 _fs_unlock();
486 return -ret;
487}
488
489//--------------------------------------------------------------------------
490
491static void fileInfoToStat(FILINFO *fno, iox_stat_t *stat)
492{
493 WORD fdate = fno->fdate;
494 WORD ftime = fno->ftime;
495 unsigned char stime[8];
496 u16 year;
497
498 stat->attr = 0777;
499 stat->size = (unsigned int)(fno->fsize);
500 stat->hisize = (unsigned int)(fno->fsize>>32);
501
502 stat->mode = FIO_S_IROTH | FIO_S_IXOTH;
503 if (fno->fattrib & AM_DIR) {
504 stat->mode |= FIO_S_IFDIR;
505 } else {
506 stat->mode |= FIO_S_IFREG;
507 }
508 if (!(fno->fattrib & AM_RDO)) {
509 stat->mode |= FIO_S_IWOTH;
510 }
511
512 // Since the VFAT file system does not support timezones, the timezone offset will not be applied.
513 // exFAT does support timezones, but the feature is not used/exposed in the FatFs library.
514 // Thus, conversion to/from JST may be incorrect.
515 // For simplicity's sake, the timezone is not read from the system configuration and timezone conversion is not done.
516
517 stime[0] = 0; // Padding
518
519 stime[4] = (fdate & 31); // Day
520 stime[5] = (fdate >> 5) & 15; // Month
521
522 year = (fdate >> 9) + 1980;
523 stime[6] = year & 0xff; // Year (low bits)
524 stime[7] = (year >> 8) & 0xff; // Year (high bits)
525
526 stime[3] = (ftime >> 11); // Hours
527 stime[2] = (ftime >> 5) & 63; // Minutes
528 stime[1] = (ftime << 1) & 31; // Seconds (multiplied by 2)
529
530 memcpy(stat->ctime, stime, sizeof(stime));
531 memcpy(stat->atime, stime, sizeof(stime));
532 memcpy(stat->mtime, stime, sizeof(stime));
533}
534
535//---------------------------------------------------------------------------
536static int fs_dread(iop_file_t *fd, iox_dirent_t *buffer)
537{
538 M_DEBUG("%s\n", __func__);
539
540 int ret;
541 FILINFO fno;
542
543 if (fd->privdata == NULL)
544 return -ENOENT;
545
546 _fs_lock();
547
548 ret = f_readdir(fd->privdata, &fno);
549
550 if (ret == FR_OK && fno.fname[0]) {
551 strncpy(buffer->name, fno.fname, 255);
552 fileInfoToStat(&fno, &(buffer->stat));
553 ret = 1;
554 } else {
555 ret = 0;
556 }
557
558 _fs_unlock();
559 return ret;
560}
561
562//---------------------------------------------------------------------------
563static int fs_getstat(iop_file_t *fd, const char *name, iox_stat_t *stat)
564{
565 M_DEBUG("%s: unit %d name %s\n", __func__, fd->unit, name);
566
567 int ret;
568 FILINFO fno;
569 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(name);
570
571 // FatFs f_stat doesn't handle the root directory, so we'll handle this case ourselves.
572 {
573 const char *name_no_leading_slash = name;
574 while (*name_no_leading_slash == '/') {
575 name_no_leading_slash += 1;
576 }
577 if ((strcmp(name_no_leading_slash, "") == 0) || (strcmp(name_no_leading_slash, ".") == 0)) {
578 if (fatfs_fs_driver_get_mounted_bd_from_index(fd->unit) == NULL) {
579 return -ENXIO;
580 }
581 // Return data indicating that it is a directory.
582 memset(stat, 0, sizeof(*stat));
584 return 0;
585 }
586 }
587
588 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(name, fd);
589
590 _fs_lock();
591
592 ret = f_stat(modified_name, &fno);
593
594 if (ret == FR_OK) {
595 fileInfoToStat(&fno, stat);
596 } else {
597 ret = -ret;
598 }
599
600 _fs_unlock();
601 return ret;
602}
603
604static int get_frag_list(FIL *file, void *rdata, unsigned int rdatalen)
605{
606 bd_fragment_t *f = (bd_fragment_t*)rdata;
607 int iMaxFragments = rdatalen / sizeof(bd_fragment_t);
608 int iFragCount = 0;
609
610 // Get the block device backing the file so we can get the starting LBA of the file system.
611 struct block_device* bd = fatfs_fs_driver_get_mounted_bd_from_index(file->obj.fs->pdrv);
612
613 DWORD iClusterStart = file->obj.sclust;
614 DWORD iClusterCurrent = iClusterStart;
615
616 do {
617 DWORD iClusterNext = get_fat(&file->obj, iClusterCurrent);
618 if (iClusterNext != (iClusterCurrent + 1)) {
619 // Fragment or file end
620 M_DEBUG("fragment: %uc - %uc + 1\n", iClusterStart, iClusterCurrent + 1);
621 if (iFragCount < iMaxFragments) {
622 u64 sector = clst2sect(file->obj.fs, iClusterStart) + bd->sectorOffset;
623 f[iFragCount].sector = sector;
624 f[iFragCount].count = clst2sect(file->obj.fs, iClusterCurrent) - clst2sect(file->obj.fs, iClusterStart) + file->obj.fs->csize;
625 DEBUG_U64_2XU32(sector);
626 M_DEBUG(" - sectors: 0x%08x%08x count %u\n", sector_u32[1], sector_u32[0], f[iFragCount].count);
627 }
628 iFragCount++;
629 iClusterStart = iClusterNext;
630 }
631 iClusterCurrent = iClusterNext;
632 } while(iClusterCurrent < file->obj.fs->n_fatent);
633
634 return iFragCount;
635}
636
637//---------------------------------------------------------------------------
638int fs_ioctl2(iop_file_t *fd, int cmd, void *data, unsigned int datalen, void *rdata, unsigned int rdatalen)
639{
640 M_DEBUG("%s cmd=%d\n", __func__, cmd);
641
642 int ret = 0;
643 FIL *file = ((FIL *)(fd->privdata));
644
645 (void)data;
646 (void)datalen;
647
648 if (file == NULL)
649 return -ENXIO;
650
651 _fs_lock();
652
653 switch (cmd) {
655 // TODO
656 // f_rename() requires two string parameters (newpath, oldpath)
657 // figure out how to get the path from the current entry object
658 ret = -ENOENT;
659 break;
661 ret = file->obj.sclust;
662 break;
664 // Check for a return buffer and copy the 64bit LBA. If no buffer is provided return an error.
665 if (rdata == NULL || rdatalen < sizeof(u64))
666 {
667 ret = -EINVAL;
668 break;
669 }
670
671 // Get the block device backing the file so we can get the starting LBA of the file system.
672 struct block_device* bd = fatfs_fs_driver_get_mounted_bd_from_index(file->obj.fs->pdrv);
673
674 *(u64*)rdata = clst2sect(file->obj.fs, file->obj.sclust) + bd->sectorOffset;
675 ret = 0;
676 break;
678 struct block_device *mounted_bd = fatfs_fs_driver_get_mounted_bd_from_index(fd->unit);
679 ret = (mounted_bd == NULL) ? -ENXIO : *(int *)(mounted_bd->name);
680
681 // Check for a return buffer and copy the whole name.
682 if (rdata != NULL)
683 strncpy(rdata, mounted_bd->name, rdatalen);
684 break;
685 }
687 ret = get_frag_list(file, NULL, 0) == 1 ? 1 : 0;
688 break;
690 ret = get_frag_list(file, rdata, rdatalen);
691 break;
693 {
694 // Check for a return buffer and copy the device number. If no buffer is provided return an error.
695 if (rdata == NULL || rdatalen < sizeof(u32))
696 {
697 ret = -EINVAL;
698 break;
699 }
700
701 struct block_device* bd = fatfs_fs_driver_get_mounted_bd_from_index(file->obj.fs->pdrv);
702 if (bd == NULL)
703 ret = -ENXIO;
704 else
705 {
706 *(u32*)rdata = bd->devNr;
707 ret = 0;
708 }
709 break;
710 }
711 default:
712 break;
713 }
714
715 _fs_unlock();
716 return ret;
717}
718
719//---------------------------------------------------------------------------
720int fs_ioctl(iop_file_t *fd, int cmd, void *data)
721{
722 return fs_ioctl2(fd, cmd, data, 1024, NULL, 0);
723}
724
725int fs_rename(iop_file_t *fd, const char *path, const char *newpath)
726{
727 M_DEBUG("%s\n", __func__);
728
729 int ret;
730 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(path);
731 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_DEFINITIONS(newpath);
732
733 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(path, fd);
734 FATFS_FS_DRIVER_NAME_ALLOC_ON_STACK_IMPLEMENTATION(newpath, fd);
735
736 // If old and new path are the same, no need to do anything
737 if (strcmp(modified_path, modified_newpath) == 0) {
738 return 0;
739 }
740
741 _fs_lock();
742
743 ret = f_rename(modified_path, modified_newpath);
744
745 _fs_unlock();
746 return -ret;
747}
748
749static int fs_devctl(iop_file_t *fd, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
750{
751 int ret;
752
753 (void)name;
754 (void)arg;
755 (void)arglen;
756 (void)buf;
757 (void)buflen;
758
759 _fs_lock();
760
761
762 switch (cmd) {
764 fatfs_fs_driver_stop_all_bd();
765 ret = FR_OK;
766 break;
767 }
769 fatfs_fs_driver_stop_single_bd(fd->unit);
770 ret = FR_OK;
771 break;
772 }
773 default: {
774 ret = -ENXIO;
775 break;
776 }
777 }
778
779 _fs_unlock();
780
781 return ret;
782}
783
784IOMANX_RETURN_VALUE_IMPL(0);
785IOMANX_RETURN_VALUE_IMPL(EIO);
786
787static iop_device_ops_t fs_functarray = {
788 IOMANX_RETURN_VALUE(0), // init
789 IOMANX_RETURN_VALUE(0), // deinit
790 IOMANX_RETURN_VALUE(EIO), // format
791 &fs_open, // open
792 &fs_close, // close
793 &fs_read, // read
794 &fs_write, // write
795 &fs_lseek, // lseek
796 &fs_ioctl, // ioctl
797 &fs_remove, // remove
798 &fs_mkdir, // mkdir
799 &fs_remove, // rmdir
800 &fs_dopen, // dopen
801 &fs_dclose, // dclose
802 &fs_dread, // dread
803 &fs_getstat, // getstat
804 IOMANX_RETURN_VALUE(EIO), // chstat
805 &fs_rename, // rename
806 IOMANX_RETURN_VALUE(EIO), // chdir
807 IOMANX_RETURN_VALUE(EIO), // sync
808 IOMANX_RETURN_VALUE(EIO), // mount
809 IOMANX_RETURN_VALUE(EIO), // umount
810 &fs_lseek64, // lseek64
811 &fs_devctl, // devctl
812 IOMANX_RETURN_VALUE(EIO), // symlink
813 IOMANX_RETURN_VALUE(EIO), // readlink
814 &fs_ioctl2, // ioctl2
815};
816static iop_device_t fs_driver = {
817 "mass",
818 IOP_DT_FS | IOP_DT_FSEXT,
819 2,
820 "FATFS driver",
821 &fs_functarray,
822};
823
824/* init file system driver */
825int InitFS(void)
826{
827 M_DEBUG("%s\n", __func__);
828
829 fs_reset();
830 fatfs_fs_driver_initialize_all_mount_info();
831
832 DelDrv(fs_driver.name);
833 return (AddDrv(&fs_driver) == 0 ? 0 : -1);
834}
#define ENOENT
Definition errno.h:23
#define ENXIO
Definition errno.h:31
#define EINVAL
Definition errno.h:63
#define EMFILE
Definition errno.h:67
#define EIO
Definition errno.h:29
#define IOP_DT_FSEXT
Definition iomanX.h:66
#define FIO_S_IROTH
Definition iox_stat.h:76
#define FIO_S_IXOTH
Definition iox_stat.h:80
#define FIO_S_IWOTH
Definition iox_stat.h:78
#define FIO_S_IFDIR
Definition iox_stat.h:45
#define FIO_S_IFREG
Definition iox_stat.h:43
#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