mgh: fix for default HDD DMA mode, that wasn't correctly set
[open-ps2-loader.git] / modules / usb / usbhdfsd / fs_driver.c
blob7c393c9e1f199cf5f64c2121a78001276fba6055
1 //---------------------------------------------------------------------------
2 //File name: fs_driver.c
3 //---------------------------------------------------------------------------
4 /*
5 * fat_driver.c - USB Mass storage driver for PS2
7 * (C) 2004, Marek Olejnik (ole00@post.cz)
8 * (C) 2004 Hermes (support for sector sizes from 512 to 4096 bytes)
9 * (C) 2004 raipsu (fs_dopen, fs_dclose, fs_dread, fs_getstat implementation)
11 * FAT filesystem layer
13 * See the file LICENSE included with this distribution for licensing terms.
15 //---------------------------------------------------------------------------
16 #include <stdio.h>
17 #include <errno.h>
18 #include <sys/stat.h>
19 #include <io_common.h>
20 #include <ioman.h>
22 #ifdef WIN32
23 #include <malloc.h>
24 #include <memory.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #else
28 #include <sysclib.h>
29 #include <thsemap.h>
30 #include <thbase.h>
31 #include <sysmem.h>
32 #define malloc(a) AllocSysMemory(0,(a), NULL)
33 #define free(a) FreeSysMemory((a))
34 #endif
36 #include "usbhd_common.h"
37 #include "fat_driver.h"
38 #include "fat_write.h"
39 #include "fat.h"
41 //#define DEBUG //comment out this line when not debugging
43 #include "mass_debug.h"
44 #include "mass_stor.h"
46 #define IOCTL_CKFREE 0xBABEC0DE //dlanor: Ioctl request code => Check free space
47 #define IOCTL_RENAME 0xFEEDC0DE //dlanor: Ioctl request code => Rename
48 #define IOCTL_GETCLUSTER 0xBEEFC0DE //jimmikaelkael: Ioctl request code => get file start cluster
49 #define IOCTL_GETDEVSECTORSIZE 0xDEADC0DE //jimmikaelkael: Ioctl request code => get mass storage device sector size
50 #define IOCTL_CHECKCHAIN 0xCAFEC0DE //polo: Ioctl request code => Check cluster chain
52 #define FLUSH_SECTORS fat_flushSectors
54 typedef struct _fs_rec {
55 int file_flag;
56 //This flag is always 1 for a file, and always 0 for a folder (different typedef)
57 //Routines that handle both must test it, and then typecast the privdata pointer
58 //to the type that is appropriate for the given case. (see also fs_dir typedef)
59 unsigned int filePos;
60 int mode; //file open mode
61 unsigned int sfnSector; //short filename sector - write support
62 int sfnOffset; //short filename offset - write support
63 int sizeChange; //flag
64 fat_dir fatdir;
65 } fs_rec;
67 typedef struct _fs_dir {
68 int file_flag;
69 //This flag is always 1 for a file, and always 0 for a folder (different typedef)
70 //Routines that handle both must test it, and then typecast the privdata pointer
71 //to the type that is appropriate for the given case. (see also fs_rec typedef)
72 int status;
73 fat_dir fatdir;
74 fat_dir_list fatdlist;
75 } fs_dir;
77 #define MAX_FILES 16
78 fs_rec fsRec[MAX_FILES]; //file info record
80 #ifndef WIN32
81 static iop_device_t fs_driver;
82 static iop_device_ops_t fs_functarray;
83 #endif
85 void fillStat(fio_stat_t *stat, fat_dir *fatdir)
87 stat->mode = FIO_SO_IROTH | FIO_SO_IXOTH;
88 if (fatdir->attr & FAT_ATTR_DIRECTORY) {
89 stat->mode |= FIO_SO_IFDIR;
90 } else {
91 stat->mode |= FIO_SO_IFREG;
93 if (!(fatdir->attr & FAT_ATTR_READONLY)) {
94 stat->mode |= FIO_SO_IWOTH;
97 stat->size = fatdir->size;
99 //set created Date: Day, Month, Year
100 stat->ctime[4] = fatdir->cdate[0];
101 stat->ctime[5] = fatdir->cdate[1];
102 stat->ctime[6] = fatdir->cdate[2];
103 stat->ctime[7] = fatdir->cdate[3];
105 //set created Time: Hours, Minutes, Seconds
106 stat->ctime[3] = fatdir->ctime[0];
107 stat->ctime[2] = fatdir->ctime[1];
108 stat->ctime[1] = fatdir->ctime[2];
110 //set accessed Date: Day, Month, Year
111 stat->atime[4] = fatdir->adate[0];
112 stat->atime[5] = fatdir->adate[1];
113 stat->atime[6] = fatdir->adate[2];
114 stat->atime[7] = fatdir->adate[3];
116 //set modified Date: Day, Month, Year
117 stat->mtime[4] = fatdir->mdate[0];
118 stat->mtime[5] = fatdir->mdate[1];
119 stat->mtime[6] = fatdir->mdate[2];
120 stat->mtime[7] = fatdir->mdate[3];
122 //set modified Time: Hours, Minutes, Seconds
123 stat->mtime[3] = fatdir->mtime[0];
124 stat->mtime[2] = fatdir->mtime[1];
125 stat->mtime[1] = fatdir->mtime[2];
128 /*************************************************************************************/
129 /* File IO functions */
130 /*************************************************************************************/
133 int nameSignature;
134 int removalTime;
135 int removalResult;
137 //---------------------------------------------------------------------------
138 fs_rec* fs_findFreeFileSlot(void) {
139 int i;
140 for (i = 0; i < MAX_FILES; i++) {
141 if (fsRec[i].file_flag == -1) {
142 return &fsRec[i];
143 break;
146 return NULL;
149 //---------------------------------------------------------------------------
150 fs_rec* fs_findFileSlotByName(const char* name) {
151 int i;
152 for (i = 0; i < MAX_FILES; i++) {
153 if (fsRec[i].file_flag >= 0 && strEqual(fsRec[i].fatdir.name, (unsigned char*) name) == 0) {
154 return &fsRec[i];
157 return NULL;
160 //---------------------------------------------------------------------------
161 static int _lock_sema_id = 0;
163 //---------------------------------------------------------------------------
164 int _fs_init_lock(void)
166 #ifndef WIN32
167 iop_sema_t sp;
169 sp.initial = 1;
170 sp.max = 1;
171 sp.option = 0;
172 sp.attr = 0;
173 if((_lock_sema_id = CreateSema(&sp)) < 0) { return(-1); }
174 #endif
176 return(0);
179 //---------------------------------------------------------------------------
180 int _fs_lock(void)
182 #ifndef WIN32
183 if(WaitSema(_lock_sema_id) != _lock_sema_id) { return(-1); }
184 #endif
185 return(0);
188 //---------------------------------------------------------------------------
189 int _fs_unlock(void)
191 #ifndef WIN32
192 SignalSema(_lock_sema_id);
193 #endif
194 return(0);
197 //---------------------------------------------------------------------------
198 void fs_reset(void)
200 int i;
201 for (i = 0; i < MAX_FILES; i++) { fsRec[i].file_flag = -1; }
202 #ifndef WIN32
203 if(_lock_sema_id >= 0) { DeleteSema(_lock_sema_id); }
204 #endif
205 _fs_init_lock();
208 //---------------------------------------------------------------------------
209 int fs_inited = 0;
211 //---------------------------------------------------------------------------
212 int fs_dummy(void)
214 return -5;
217 //---------------------------------------------------------------------------
218 int fs_init(iop_device_t *driver)
220 if(fs_inited) { return(1); }
222 fs_reset();
224 fs_inited = 1;
225 return 1;
228 //---------------------------------------------------------------------------
229 int fs_open(iop_file_t* fd, const char *name, int mode) {
230 fat_driver* fatd;
231 fs_rec* rec = NULL;
232 int ret;
233 unsigned int cluster;
235 _fs_lock();
237 XPRINTF("USBHDFSD: fs_open called: %s mode=%X \n", name, mode) ;
239 fatd = fat_getData(fd->unit);
240 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
242 #ifndef WRITE_SUPPORT
243 //read only support
244 if (mode != 0 && mode != O_RDONLY) { //correct O_RDONLY number?
245 XPRINTF("USBHDFSD: mode (%d) != O_RDONLY (%d) \n", mode, O_RDONLY);
246 return -EROFS;
248 #endif
250 #ifdef WRITE_SUPPORT
251 fs_rec* rec2 = NULL;
252 char escapeNotExist;
254 //check if the file is already open
255 rec2 = fs_findFileSlotByName(name);
256 if (rec2 != NULL) {
257 if ((mode & O_WRONLY) || //current file is opened for write
258 (rec2->mode & O_WRONLY) ) {//other file is opened for write
259 _fs_unlock();
260 return -EACCES;
263 #endif
265 //check if the slot is free
266 rec = fs_findFreeFileSlot();
267 if (rec == NULL) { _fs_unlock(); return -EMFILE; }
269 #ifdef WRITE_SUPPORT
270 if((mode & O_WRONLY)) { //dlanor: corrected bad test condition
271 cluster = 0; //start from root
273 escapeNotExist = 1;
274 if (mode & O_CREAT) {
275 XPRINTF("USBHDFSD: FAT I: O_CREAT detected!\n");
276 escapeNotExist = 0;
279 rec->sfnSector = 0;
280 rec->sfnOffset = 0;
281 ret = fat_createFile(fatd, name, 0, escapeNotExist, &cluster, &rec->sfnSector, &rec->sfnOffset);
282 if (ret < 0) {
283 _fs_unlock();
284 return ret;
286 //the file already exist but mode is set to truncate
287 if (ret == 2 && (mode & O_TRUNC)) {
288 XPRINTF("USBHDFSD: FAT I: O_TRUNC detected!\n");
289 fat_truncateFile(fatd, cluster, rec->sfnSector, rec->sfnOffset);
292 #endif
294 //find the file
295 cluster = 0; //allways start from root
296 XPRINTF("USBHDFSD: Calling fat_getFileStartCluster from fs_open\n");
297 ret = fat_getFileStartCluster(fatd, name, &cluster, &rec->fatdir);
298 if (ret < 0) {
299 _fs_unlock();
300 return ret;
302 if ((rec->fatdir.attr & FAT_ATTR_DIRECTORY) == FAT_ATTR_DIRECTORY) {
303 // Can't open a directory with fioOpen
304 _fs_unlock();
305 return -EISDIR;
308 rec->file_flag = 1;
309 rec->mode = mode;
310 rec->filePos = 0;
311 rec->sizeChange = 0;
313 #ifdef WRITE_SUPPORT
314 if ((mode & O_APPEND) && (mode & O_WRONLY)) {
315 XPRINTF("USBHDFSD: FAT I: O_APPEND detected!\n");
316 rec->filePos = rec->fatdir.size;
318 #endif
320 //store the slot to user parameters
321 fd->privdata = rec;
323 _fs_unlock();
324 return 1;
327 //---------------------------------------------------------------------------
328 int fs_close(iop_file_t* fd) {
329 fat_driver* fatd;
330 fs_rec* rec = (fs_rec*)fd->privdata;
331 fd->privdata = 0;
333 if (rec == 0)
334 return -EBADF;
336 _fs_lock();
338 rec->file_flag = -1;
340 fatd = fat_getData(fd->unit);
341 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
343 #ifdef WRITE_SUPPORT
344 if ((rec->mode & O_WRONLY)) {
345 //update direntry size and time
346 if (rec->sizeChange) {
347 fat_updateSfn(fatd, rec->fatdir.size, rec->sfnSector, rec->sfnOffset);
350 FLUSH_SECTORS(fatd);
352 #endif
354 _fs_unlock();
355 return 0;
358 //---------------------------------------------------------------------------
359 int fs_lseek(iop_file_t* fd, unsigned long offset, int whence) {
360 fat_driver* fatd;
361 fs_rec* rec = (fs_rec*)fd->privdata;
363 if (rec == 0)
364 return -EBADF;
366 _fs_lock();
368 fatd = fat_getData(fd->unit);
369 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
371 switch(whence) {
372 case SEEK_SET:
373 rec->filePos = offset;
374 break;
375 case SEEK_CUR:
376 rec->filePos += offset;
377 break;
378 case SEEK_END:
379 rec->filePos = rec->fatdir.size + offset;
380 break;
381 default:
382 _fs_unlock();
383 return -1;
385 if (rec->filePos < 0) {
386 rec->filePos = 0;
388 if (rec->filePos > rec->fatdir.size) {
389 rec->filePos = rec->fatdir.size;
392 _fs_unlock();
393 return rec->filePos;
396 //---------------------------------------------------------------------------
397 int fs_write(iop_file_t* fd, void * buffer, int size )
399 #ifdef WRITE_SUPPORT
400 fat_driver* fatd;
401 fs_rec* rec = (fs_rec*)fd->privdata;
402 int result;
403 int updateClusterIndices = 0;
405 if (rec == 0)
406 return -EBADF;
408 _fs_lock();
410 fatd = fat_getData(fd->unit);
411 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
413 if (rec->file_flag != 1) {
414 _fs_unlock();
415 return -EACCES;
418 if (!(rec->mode & O_WRONLY)) {
419 _fs_unlock();
420 return -EACCES;
423 if (size <= 0) { _fs_unlock(); return 0; }
425 result = fat_writeFile(fatd, &rec->fatdir, &updateClusterIndices, rec->filePos, (unsigned char*) buffer, size);
426 if (result > 0) { //write succesful
427 rec->filePos += result;
428 if (rec->filePos > rec->fatdir.size) {
429 rec->fatdir.size = rec->filePos;
430 rec->sizeChange = 1;
431 //if new clusters allocated - then update file cluster indices
432 if (updateClusterIndices) {
433 fat_setFatDirChain(fatd, &rec->fatdir);
438 _fs_unlock();
439 return result;
440 #else
441 return -EROFS;
442 #endif
445 //---------------------------------------------------------------------------
446 int fs_read(iop_file_t* fd, void * buffer, int size ) {
447 fat_driver* fatd;
448 fs_rec* rec = (fs_rec*)fd->privdata;
449 int result;
451 if (rec == 0)
452 return -EBADF;
454 _fs_lock();
456 fatd = fat_getData(fd->unit);
457 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
459 if (rec->file_flag != 1) {
460 _fs_unlock();
461 return -EACCES;
464 if (!(rec->mode & O_RDONLY)) {
465 _fs_unlock();
466 return -EACCES;
469 if (size<=0) {
470 _fs_unlock();
471 return 0;
474 if ((rec->filePos+size) > rec->fatdir.size) {
475 size = rec->fatdir.size - rec->filePos;
478 result = fat_readFile(fatd, &rec->fatdir, rec->filePos, (unsigned char*) buffer, size);
479 if (result > 0) { //read succesful
480 rec->filePos += result;
483 _fs_unlock();
484 return result;
488 //---------------------------------------------------------------------------
489 int getNameSignature(const char *name) {
490 int ret;
491 int i;
492 ret = 0;
494 for (i=0; name[i] != 0 ; i++) ret += (name[i]*i/2 + name[i]);
495 return ret;
498 //---------------------------------------------------------------------------
499 int getMillis()
501 #ifdef WIN32
502 return 0;
503 #else
504 iop_sys_clock_t clock;
505 u32 sec, usec;
507 GetSystemTime(&clock);
508 SysClock2USec(&clock, &sec, &usec);
509 return (sec*1000) + (usec/1000);
510 #endif
513 //---------------------------------------------------------------------------
514 int fs_remove (iop_file_t *fd, const char *name) {
515 #ifdef WRITE_SUPPORT
516 fat_driver* fatd;
517 fs_rec* rec;
518 int result;
520 _fs_lock();
522 fatd = fat_getData(fd->unit);
523 if (fatd == NULL)
525 result = -ENODEV;
526 removalResult = result;
527 _fs_unlock();
528 return result;
531 rec = fs_findFileSlotByName(name);
532 //store filename signature and time of removal
533 nameSignature = getNameSignature(name);
534 removalTime = getMillis();
536 //file is opened - can't delete the file
537 if (rec != NULL) {
538 result = -EINVAL;
539 removalResult = result;
540 _fs_unlock();
541 return result;
544 result = fat_deleteFile(fatd, name, 0);
545 FLUSH_SECTORS(fatd);
546 removalTime = getMillis(); //update removal time
547 removalResult = result;
549 _fs_unlock();
550 return result;
551 #else
552 return fs_dummy();
553 #endif
556 //---------------------------------------------------------------------------
557 int fs_mkdir (iop_file_t *fd, const char *name) {
558 #ifdef WRITE_SUPPORT
559 fat_driver* fatd;
560 int ret;
561 int sfnOffset;
562 unsigned int sfnSector;
563 unsigned int cluster;
564 int sig, millis;
566 _fs_lock();
568 fatd = fat_getData(fd->unit);
569 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
571 XPRINTF("USBHDFSD: fs_mkdir: name=%s \n",name);
572 //workaround for bug that invokes fioMkdir right after fioRemove
573 sig = getNameSignature(name);
574 millis = getMillis();
575 if (sig == nameSignature && (millis - removalTime) < 1000) {
576 _fs_unlock();
577 return removalResult; //return the original return code from fs_remove
580 ret = fat_createFile(fatd, name, 1, 0, &cluster, &sfnSector, &sfnOffset);
582 //directory of the same name already exist
583 if (ret == 2) {
584 ret = -EEXIST;
586 FLUSH_SECTORS(fatd);
588 _fs_unlock();
589 return ret;
590 #else
591 return fs_dummy();
592 #endif
595 //---------------------------------------------------------------------------
596 // NOTE! you MUST call fioRmdir with device number in the name
597 // or else this fs_rmdir function is never called.
598 // example: fioRmdir("mass:/dir1"); // <-- doesn't work (bug?)
599 // fioRmdir("mass0:/dir1"); // <-- works fine
600 int fs_rmdir (iop_file_t *fd, const char *name) {
601 #ifdef WRITE_SUPPORT
602 fat_driver* fatd;
603 int ret;
605 _fs_lock();
607 fatd = fat_getData(fd->unit);
608 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
610 ret = fat_deleteFile(fatd, name, 1);
611 FLUSH_SECTORS(fatd);
612 _fs_unlock();
613 return ret;
614 #else
615 return fs_dummy();
616 #endif
619 //---------------------------------------------------------------------------
620 int fs_dopen (iop_file_t *fd, const char *name)
622 fat_driver* fatd;
623 int is_root = 0;
624 fs_dir* rec;
626 _fs_lock();
628 XPRINTF("USBHDFSD: fs_dopen called: unit %d name %s\n", fd->unit, name);
630 fatd = fat_getData(fd->unit);
631 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
633 if( ((name[0] == '/') && (name[1] == '\0'))
634 ||((name[0] == '/') && (name[1] == '.') && (name[2] == '\0')))
636 name = "/";
637 is_root = 1;
640 fd->privdata = (void*)malloc(sizeof(fs_dir));
641 memset(fd->privdata, 0, sizeof(fs_dir)); //NB: also implies "file_flag = 0;"
642 rec = (fs_dir *) fd->privdata;
644 rec->status = fat_getFirstDirentry(fatd, (char*)name, &rec->fatdlist, &rec->fatdir);
646 // root directory may have no entries, nothing else may.
647 if(rec->status == 0 && !is_root)
648 rec->status = -EFAULT;
650 if (rec->status < 0)
651 free(fd->privdata);
653 _fs_unlock();
654 return rec->status;
657 //---------------------------------------------------------------------------
658 int fs_dclose (iop_file_t *fd)
660 if (fd->privdata == 0)
661 return -EBADF;
663 _fs_lock();
664 XPRINTF("USBHDFSD: fs_dclose called: unit %d\n", fd->unit);
665 free(fd->privdata);
666 fd->privdata = 0;
667 _fs_unlock();
668 return 0;
671 //---------------------------------------------------------------------------
672 int fs_dread (iop_file_t *fd, fio_dirent_t *buffer)
674 fat_driver* fatd;
675 int ret;
676 fs_dir* rec = (fs_dir *) fd->privdata;
678 if (rec == 0)
679 return -EBADF;
681 _fs_lock();
683 XPRINTF("USBHDFSD: fs_dread called: unit %d\n", fd->unit);
685 fatd = fat_getData(fd->unit);
686 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
688 while (rec->status > 0
689 && (rec->fatdir.attr & FAT_ATTR_VOLUME_LABEL
690 || ((rec->fatdir.attr & (FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM)) == (FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM))))
691 rec->status = fat_getNextDirentry(fatd, &rec->fatdlist, &rec->fatdir);
693 ret = rec->status;
694 if (rec->status >= 0)
696 memset(buffer, 0, sizeof(fio_dirent_t));
697 fillStat(&buffer->stat, &rec->fatdir);
698 strcpy(buffer->name, (const char*) rec->fatdir.name);
701 if (rec->status > 0)
702 rec->status = fat_getNextDirentry(fatd, &rec->fatdlist, &rec->fatdir);
704 _fs_unlock();
705 return ret;
708 //---------------------------------------------------------------------------
709 int fs_getstat(iop_file_t *fd, const char *name, fio_stat_t *stat)
711 fat_driver* fatd;
712 int ret;
713 unsigned int cluster = 0;
714 fat_dir fatdir;
716 _fs_lock();
718 XPRINTF("USBHDFSD: fs_getstat called: unit %d name %s\n", fd->unit, name);
720 fatd = fat_getData(fd->unit);
721 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
723 XPRINTF("USBHDFSD: Calling fat_getFileStartCluster from fs_getstat\n");
724 ret = fat_getFileStartCluster(fatd, name, &cluster, &fatdir);
725 if (ret < 0) {
726 _fs_unlock();
727 return ret;
730 memset(stat, 0, sizeof(fio_stat_t));
731 fillStat(stat, &fatdir);
733 _fs_unlock();
734 return 0;
737 //---------------------------------------------------------------------------
738 int fs_chstat (iop_file_t *fd, const char *name, fio_stat_t *stat, unsigned int a)
740 return fs_dummy();
743 //---------------------------------------------------------------------------
744 int fs_deinit (iop_device_t *fd)
746 return fs_dummy();
749 //---------------------------------------------------------------------------
750 int fs_format (iop_file_t *fd)
752 return fs_dummy();
755 //---------------------------------------------------------------------------
756 unsigned int fs_getFileSector(iop_file_t *fd, char *name)
758 fat_driver* fatd;
759 int ret;
760 unsigned int cluster = 0;
761 fat_dir fatDir;
763 fatd = fat_getData(fd->unit);
764 if (fatd == NULL)
765 return 0;
767 ret = fat_getFileStartCluster(fatd, name, &cluster, &fatDir);
768 if (ret < 0)
769 return 0;
771 return fat_cluster2sector(&fatd->partBpb, cluster);
774 //---------------------------------------------------------------------------
775 int fs_checkClusterChain(iop_file_t *fd, char *name)
777 int chain_end = 0;
778 fat_driver* fatd;
779 fs_rec* rec = NULL;
780 int ret, chain_size;
781 unsigned int cluster = 0;
783 fatd = fat_getData(fd->unit);
784 if (fatd == NULL)
785 return 0;
787 rec = fs_findFreeFileSlot();
788 if (rec == NULL)
789 return 0;
791 ret = fat_getFileStartCluster(fatd, name, &cluster, &rec->fatdir);
792 if (ret < 0) {
793 rec->file_flag = -1;
794 return 0;
797 rec->file_flag = -1;
799 // Check cluster chain (write operation can cause dammage if file is fragmented)
800 while (chain_end == 0) {
801 chain_size = fat_getClusterChain(fatd, cluster, fatd->cbuf, MAX_DIR_CLUSTER, 1);
803 if(fatd->cbuf[0] != fatd->cbuf[chain_size-1] - (chain_size-1))
804 return 0;
806 if (chain_size == MAX_DIR_CLUSTER) {
807 cluster = fatd->cbuf[chain_size - 1];
808 } else {
809 chain_end = 1;
813 return 1;
816 //---------------------------------------------------------------------------
817 int fs_ioctl(iop_file_t *fd, unsigned long request, void *data)
819 fat_driver* fatd;
820 fs_dir* rec = (fs_dir *) fd->privdata;
821 int ret;
823 if (rec == 0)
824 return -EBADF;
826 _fs_lock();
828 fatd = fat_getData(fd->unit);
829 if (fatd == NULL) { _fs_unlock(); return -ENODEV; }
831 switch (request) {
832 case IOCTL_CKFREE: //Request to calculate free space (ignore file/folder selected)
833 ret = fs_dummy();
834 break;
835 case IOCTL_RENAME: //Request to rename opened file/folder
836 ret = fs_dummy();
837 break;
838 case IOCTL_GETCLUSTER:
839 ret = fs_getFileSector(fd, (char *)data);
840 break;
841 case IOCTL_GETDEVSECTORSIZE:
842 ret = mass_stor_sectorsize(fatd->dev);
843 break;
844 case IOCTL_CHECKCHAIN:
845 ret = fs_checkClusterChain(fd, (char *)data);
846 break;
847 default:
848 ret = fs_dummy();
851 _fs_unlock();
852 return ret;
855 #ifndef WIN32
856 /* init file system driver */
857 int InitFS()
859 fs_driver.name = "mass";
860 fs_driver.type = IOP_DT_FS;
861 fs_driver.version = 2;
862 fs_driver.desc = "Usb mass storage driver";
863 fs_driver.ops = &fs_functarray;
865 fs_functarray.init = fs_init;
866 fs_functarray.deinit = fs_deinit;
867 fs_functarray.format = fs_format;
868 fs_functarray.open = fs_open;
869 fs_functarray.close = fs_close;
870 fs_functarray.read = fs_read;
871 fs_functarray.write = fs_write;
872 fs_functarray.lseek = fs_lseek;
873 fs_functarray.ioctl = fs_ioctl;
874 fs_functarray.remove = fs_remove;
875 fs_functarray.mkdir = fs_mkdir;
876 fs_functarray.rmdir = fs_rmdir;
877 fs_functarray.dopen = fs_dopen;
878 fs_functarray.dclose = fs_dclose;
879 fs_functarray.dread = fs_dread;
880 fs_functarray.getstat = fs_getstat;
881 fs_functarray.chstat = fs_chstat;
883 DelDrv("mass");
884 AddDrv(&fs_driver);
886 // should return an error code if AddDrv fails...
887 return(0);
889 #endif
891 //---------------------------------------------------------------------------
892 //End of file: fs_driver.c
893 //---------------------------------------------------------------------------