2 * FreeRTOS+FAT SL V1.0.1 (C) 2014 HCC Embedded
\r
4 * The FreeRTOS+FAT SL license terms are different to the FreeRTOS license
\r
7 * FreeRTOS+FAT SL uses a dual license model that allows the software to be used
\r
8 * under a standard GPL open source license, or a commercial license. The
\r
9 * standard GPL license (unlike the modified GPL license under which FreeRTOS
\r
10 * itself is distributed) requires that all software statically linked with
\r
11 * FreeRTOS+FAT SL is also distributed under the same GPL V2 license terms.
\r
12 * Details of both license options follow:
\r
14 * - Open source licensing -
\r
15 * FreeRTOS+FAT SL is a free download and may be used, modified, evaluated and
\r
16 * distributed without charge provided the user adheres to version two of the
\r
17 * GNU General Public License (GPL) and does not remove the copyright notice or
\r
18 * this text. The GPL V2 text is available on the gnu.org web site, and on the
\r
19 * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.
\r
21 * - Commercial licensing -
\r
22 * Businesses and individuals who for commercial or other reasons cannot comply
\r
23 * with the terms of the GPL V2 license must obtain a commercial license before
\r
24 * incorporating FreeRTOS+FAT SL into proprietary software for distribution in
\r
25 * any form. Commercial licenses can be purchased from
\r
26 * http://shop.freertos.org/fat_sl and do not require any source files to be
\r
29 * FreeRTOS+FAT SL is distributed in the hope that it will be useful. You
\r
30 * cannot use FreeRTOS+FAT SL unless you agree that you use the software 'as
\r
31 * is'. FreeRTOS+FAT SL is provided WITHOUT ANY WARRANTY; without even the
\r
32 * implied warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
\r
33 * PARTICULAR PURPOSE. Real Time Engineers Ltd. and HCC Embedded disclaims all
\r
34 * conditions and terms, be they implied, expressed, or statutory.
\r
36 * http://www.FreeRTOS.org
\r
37 * http://www.FreeRTOS.org/FreeRTOS-Plus
\r
41 #include "../../api/fat_sl.h"
\r
42 #include "../../psp/include/psp_string.h"
\r
51 #include "../../version/ver_fat_sl.h"
\r
52 #if VER_FAT_SL_MAJOR != 5 || VER_FAT_SL_MINOR != 2
\r
53 #error Incompatible FAT_SL version number!
\r
56 #if F_FS_THREAD_AWARE == 1
\r
60 F_VOLUME gl_volume; /* only one volume */
\r
61 F_FILE gl_file; /* file */
\r
62 char gl_sector[F_SECTOR_SIZE]; /* actual sector */
\r
64 #if F_FILE_CHANGED_EVENT
\r
65 F_FILE_CHANGED_EVENTFUNC f_filechangedevent;
\r
69 /* Defines the number of sectors per cluster on a sector number basis */
\r
72 unsigned long max_sectors;
\r
73 unsigned char sector_per_cluster;
\r
76 static const t_FAT32_CS FAT32_CS[] =
\r
78 { 0x00020000, 1 } /* ->64MB */
\r
79 , { 0x00040000, 2 } /* ->128MB */
\r
80 , { 0x00080000, 4 } /* ->256MB */
\r
81 , { 0x01000000, 8 } /* ->8GB */
\r
82 , { 0x02000000, 16 } /* ->16GB */
\r
83 , { 0x0ffffff0, 32 } /* -> ... */
\r
87 /****************************************************************************
\r
89 * _f_writebootrecord
\r
91 * writing boot record onto a volume, it uses number of hidden sector variable
\r
94 * phy - media physical descriptor
\r
97 * error code or zero if successful
\r
99 ***************************************************************************/
\r
100 static unsigned char _f_writebootrecord ( F_PHY * phy )
\r
102 unsigned char jump_code[] =
\r
106 unsigned char oem_name[] = "MSDOS5.0";
\r
107 unsigned char executable_marker[] =
\r
111 unsigned char * ptr = (unsigned char *)gl_sector;
\r
113 unsigned short mre;
\r
116 unsigned char _n = 0;
\r
118 if ( gl_volume.mediatype == F_FAT32_MEDIA )
\r
119 { /*write FS_INFO*/
\r
125 psp_memset( ptr, 0, F_SECTOR_SIZE );
\r
127 for ( a = 0 ; a < rs ; a++ )
\r
129 ret = _f_writeglsector( a ); /*erase reserved area*/
\r
136 ptr = _setlong( 0x41615252, ptr ); /*signature*/
\r
137 ptr = _setcharzero( 480, ptr ); /*reserved*/
\r
138 ptr = _setlong( 0x61417272, ptr ); /*signature*/
\r
139 ptr = _setlong( 0xffffffff, ptr ); /*no last*/
\r
140 ptr = _setlong( 0xffffffff, ptr ); /*no hint*/
\r
141 ptr = _setcharzero( 12, ptr ); /*reserved*/
\r
142 ptr = _setlong( 0xaa550000, ptr ); /*trail*/
\r
145 ret = _f_writeglsector( 1 ); /*write FSINFO*/
\r
151 ret = _f_writeglsector( 1 + 6 ); /*write FSINFO*/
\r
163 ptr = (unsigned char *)gl_sector;
\r
164 ptr = _setchar( jump_code, sizeof( jump_code ), ptr );
\r
165 ptr = _setchar( oem_name, sizeof( oem_name ) - 1, ptr );
\r
166 ptr = _setword( F_SECTOR_SIZE, ptr );
\r
167 *ptr++ = gl_volume.bootrecord.sector_per_cluster;
\r
168 ptr = _setword( rs, ptr ); /* reserved sectors */
\r
169 *ptr++ = 2; /* number of FATs */
\r
170 ptr = _setword( mre, ptr ); /* max root entry */
\r
171 if ( phy->number_of_sectors < 0x10000 )
\r
173 ptr = _setword( (unsigned short)phy->number_of_sectors, ptr );
\r
177 ptr = _setword( 0, ptr );
\r
180 *ptr++ = 0xf0; /* media descriptor */
\r
181 ptr = _setword( (unsigned short)gl_volume.bootrecord.sector_per_FAT, ptr );
\r
182 ptr = _setword( phy->sector_per_track, ptr );
\r
183 ptr = _setword( phy->number_of_heads, ptr );
\r
184 ptr = _setlong( 0, ptr ); /* number of hidden sectors */
\r
185 if ( phy->number_of_sectors >= 0x10000 )
\r
187 ptr = _setlong( phy->number_of_sectors, ptr );
\r
191 ptr = _setlong( 0, ptr ); /* number of sectors */
\r
194 if ( gl_volume.mediatype == F_FAT32_MEDIA )
\r
196 ptr = _setlong( gl_volume.bootrecord.sector_per_FAT32, ptr );
\r
197 ptr = _setword( 0, ptr );
\r
198 ptr = _setword( 0, ptr );
\r
199 ptr = _setlong( 2, ptr );
\r
200 ptr = _setword( 1, ptr );
\r
201 ptr = _setword( 6, ptr );
\r
202 ptr = _setchar( NULL, 12, ptr );
\r
207 ptr = _setword( 0, ptr ); /* logical drive num */
\r
208 *ptr++ = 0x29; /* extended signature */
\r
209 ptr = _setlong( 0x11223344, ptr );
\r
210 ptr = _setchar( (const unsigned char *)"NO NAME ", 11, ptr ); /* volume name */
\r
212 switch ( gl_volume.mediatype )
\r
214 case F_FAT12_MEDIA:
\r
215 ptr = _setchar( (const unsigned char *)"FAT12 ", 8, ptr );
\r
218 case F_FAT16_MEDIA:
\r
219 ptr = _setchar( (const unsigned char *)"FAT16 ", 8, ptr );
\r
222 case F_FAT32_MEDIA:
\r
223 ptr = _setchar( (const unsigned char *)"FAT32 ", 8, ptr );
\r
227 return F_ERR_INVALIDMEDIA;
\r
230 ptr = _setchar( 0, 448 - _n, ptr );
\r
231 ptr = _setchar( executable_marker, sizeof( executable_marker ), ptr );
\r
235 ret = _f_writeglsector( 6 );
\r
243 return _f_writeglsector( 0 ); /*write bootrecord*/
\r
244 } /* _f_writebootrecord */
\r
247 /****************************************************************************
\r
252 * phy - media physical descriptor
\r
254 * calculate relative sector position from boot record
\r
256 ***************************************************************************/
\r
257 static unsigned char _f_buildsectors ( F_PHY * phy )
\r
259 gl_volume.mediatype = F_UNKNOWN_MEDIA;
\r
262 if ( gl_volume.bootrecord.sector_per_FAT )
\r
264 gl_volume.firstfat.sector = 1;
\r
265 gl_volume.firstfat.num = gl_volume.bootrecord.sector_per_FAT;
\r
266 gl_volume.root.sector = gl_volume.firstfat.sector + ( gl_volume.firstfat.num * (unsigned long)( gl_volume.bootrecord.number_of_FATs ) );
\r
267 gl_volume.root.num = ( 512 * sizeof( F_DIRENTRY ) ) / F_SECTOR_SIZE;
\r
269 gl_volume._tdata.sector = gl_volume.root.sector + gl_volume.root.num;
\r
270 gl_volume._tdata.num = 0; /*??*/
\r
274 gl_volume.firstfat.sector = ( 32 + 4 );
\r
275 gl_volume.firstfat.num = gl_volume.bootrecord.sector_per_FAT32;
\r
276 gl_volume._tdata.sector = gl_volume.firstfat.sector;
\r
277 gl_volume._tdata.sector += gl_volume.firstfat.num * (unsigned long)( gl_volume.bootrecord.number_of_FATs );
\r
278 gl_volume._tdata.num = 0; /*??*/
\r
281 unsigned long sectorcou = gl_volume.bootrecord.sector_per_cluster;
\r
282 gl_volume.root.sector = ( ( gl_volume.bootrecord.rootcluster - 2 ) * sectorcou ) + gl_volume._tdata.sector;
\r
283 gl_volume.root.num = gl_volume.bootrecord.sector_per_cluster;
\r
288 unsigned long maxcluster;
\r
289 maxcluster = phy->number_of_sectors;
\r
290 maxcluster -= gl_volume._tdata.sector;
\r
291 maxcluster /= gl_volume.bootrecord.sector_per_cluster;
\r
292 gl_volume.maxcluster = maxcluster;
\r
295 if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xfff ) )
\r
297 gl_volume.mediatype = F_FAT12_MEDIA;
\r
299 else if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xffff ) )
\r
301 gl_volume.mediatype = F_FAT16_MEDIA;
\r
305 gl_volume.mediatype = F_FAT32_MEDIA;
\r
309 } /* _f_buildsectors */
\r
313 /****************************************************************************
\r
317 * preparing boot record for formatting, it sets and calculates values
\r
320 * phy - media physical descriptor
\r
321 * f_bootrecord - which bootrecord need to be prepare
\r
322 * number_of_hidden_sectors - where boot record starts
\r
323 * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA
\r
326 * error code or zero if successful
\r
328 ***************************************************************************/
\r
329 static unsigned char _f_prepareformat ( F_PHY * phy, unsigned char fattype )
\r
331 if ( !phy->number_of_sectors )
\r
333 return F_ERR_INVALIDSECTOR;
\r
336 gl_volume.bootrecord.number_of_FATs = 2;
\r
337 gl_volume.bootrecord.media_descriptor = 0xf0;
\r
339 if ( fattype != F_FAT32_MEDIA )
\r
344 case F_FAT12_MEDIA:
\r
345 _n = F_CLUSTER_RESERVED & 0xfff;
\r
348 case F_FAT16_MEDIA:
\r
349 _n = F_CLUSTER_RESERVED & 0xffff;
\r
353 return F_ERR_INVFATTYPE;
\r
356 gl_volume.bootrecord.sector_per_cluster = 1;
\r
357 while ( gl_volume.bootrecord.sector_per_cluster )
\r
359 if ( phy->number_of_sectors / gl_volume.bootrecord.sector_per_cluster < _n )
\r
364 gl_volume.bootrecord.sector_per_cluster <<= 1;
\r
367 if ( !gl_volume.bootrecord.sector_per_cluster )
\r
369 return F_ERR_MEDIATOOLARGE;
\r
376 for ( i = 0 ; i<( sizeof( FAT32_CS ) / sizeof( t_FAT32_CS ) ) - 1 && phy->number_of_sectors>FAT32_CS[i].max_sectors ; i++ )
\r
380 gl_volume.bootrecord.sector_per_cluster = FAT32_CS[i].sector_per_cluster;
\r
383 if ( !gl_volume.bootrecord.sector_per_cluster )
\r
385 return F_ERR_INVALIDMEDIA; /*fat16 cannot be there*/
\r
389 long secpercl = gl_volume.bootrecord.sector_per_cluster;
\r
390 long nfat = gl_volume.bootrecord.number_of_FATs;
\r
391 unsigned long roots;
\r
392 unsigned long fatsec;
\r
394 roots = ( 512 * sizeof( F_DIRENTRY ) ) / F_SECTOR_SIZE;
\r
398 case F_FAT32_MEDIA:
\r
400 unsigned long _n = (unsigned long)( 128 * secpercl + nfat );
\r
401 fatsec = ( phy->number_of_sectors - ( 32 + 4 ) + 2 * secpercl );
\r
402 fatsec += ( _n - 1 );
\r
404 gl_volume.bootrecord.sector_per_FAT32 = fatsec;
\r
405 gl_volume.bootrecord.sector_per_FAT = 0;
\r
409 case F_FAT16_MEDIA:
\r
411 unsigned long _n = (unsigned long)( 256 * secpercl + nfat );
\r
412 fatsec = ( phy->number_of_sectors - 1 - roots + 2 * secpercl );
\r
413 fatsec += ( _n - 1 );
\r
415 gl_volume.bootrecord.sector_per_FAT = (unsigned short)( fatsec );
\r
419 case F_FAT12_MEDIA:
\r
421 unsigned long _n = (unsigned long)( 1024 * secpercl + 3 * nfat );
\r
422 fatsec = ( phy->number_of_sectors - 1 - roots + 2 * secpercl );
\r
424 fatsec += ( _n - 1 );
\r
426 gl_volume.bootrecord.sector_per_FAT = (unsigned short)( fatsec );
\r
431 return F_ERR_INVALIDMEDIA;
\r
436 } /* _f_prepareformat */
\r
440 /****************************************************************************
\r
444 * erase fats, erase root directory, reset variables after formatting
\r
447 * phy - media physical descriptor
\r
448 * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA
\r
451 * error code or zero if successful
\r
453 ***************************************************************************/
\r
454 static unsigned char _f_postformat ( F_PHY * phy, unsigned char fattype )
\r
459 _f_buildsectors( phy ); /*get positions*/
\r
460 if ( gl_volume.mediatype != fattype )
\r
462 return F_ERR_MEDIATOOSMALL;
\r
465 gl_volume.fatsector = (unsigned long)( -1 );
\r
468 unsigned char * ptr = (unsigned char *)gl_sector;
\r
469 unsigned char j = 2;
\r
472 psp_memset( ptr, 0, F_SECTOR_SIZE );
\r
474 switch ( gl_volume.mediatype )
\r
476 case F_FAT16_MEDIA:
\r
480 case F_FAT32_MEDIA:
\r
485 *ptr = gl_volume.bootrecord.media_descriptor;
\r
486 psp_memset( ptr + 1, 0xff, j );
\r
487 if ( gl_volume.mediatype == F_FAT32_MEDIA )
\r
489 *( ptr + 8 ) = (unsigned char)( F_CLUSTER_LAST & 0xff );
\r
492 (void)_f_writeglsector( gl_volume.firstfat.sector );
\r
493 (void)_f_writeglsector( gl_volume.firstfat.sector + gl_volume.firstfat.num );
\r
494 psp_memset( ptr, 0, ( j + 1 ) );
\r
496 for ( i = 1 ; i < gl_volume.firstfat.num ; i++ )
\r
498 (void)_f_writeglsector( gl_volume.firstfat.sector + i );
\r
499 (void)_f_writeglsector( gl_volume.firstfat.sector + i + gl_volume.firstfat.num );
\r
503 for ( a = 0 ; a < gl_volume.root.num ; a++ ) /*reset root direntries*/
\r
505 ret = _f_writeglsector( gl_volume.root.sector + a );
\r
512 return _f_writebootrecord( phy );
\r
513 } /* _f_postformat */
\r
516 /****************************************************************************
\r
520 * Making a complete format on media, independently from master boot record,
\r
521 * according to media physical
\r
524 * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA
\r
527 * error code or zero if successful
\r
529 ***************************************************************************/
\r
530 unsigned char fn_hardformat ( unsigned char fattype )
\r
536 ret = _f_getvolume();
\r
537 if ( ret && ( ret != F_ERR_NOTFORMATTED ) )
\r
542 gl_volume.state = F_STATE_NEEDMOUNT;
\r
544 psp_memset( &phy, 0, sizeof( F_PHY ) );
\r
546 mdrv_ret = mdrv->getphy( mdrv, &phy );
\r
549 return F_ERR_ONDRIVE;
\r
552 ret = _f_prepareformat( &phy, fattype ); /*no partition*/
\r
558 return _f_postformat( &phy, fattype );
\r
559 } /* fn_hardformat */
\r
564 /****************************************************************************
\r
566 * _f_readbootrecord
\r
568 * read boot record from a volume, it detects if there is MBR on the media
\r
572 * error code or zero if successful
\r
574 ***************************************************************************/
\r
575 static unsigned char _f_readbootrecord ( void )
\r
578 unsigned char * ptr = (unsigned char *)gl_sector;
\r
579 unsigned long maxcluster, _n;
\r
580 unsigned long first_sector = 0;
\r
582 gl_volume.mediatype = F_UNKNOWN_MEDIA;
\r
585 ret = _f_readglsector( 0 );
\r
592 if ( ( ptr[0x1fe] != 0x55 ) || ( ptr[0x1ff] != 0xaa ) )
\r
594 return F_ERR_NOTFORMATTED; /*??*/
\r
597 if ( ( ptr[0] != 0xeb ) && ( ptr[0] != 0xe9 ) )
\r
599 first_sector = _f_getlong( &ptr[0x08 + 0x1be] ); /*start sector for 1st partioon*/
\r
601 ret = _f_readglsector( first_sector );
\r
607 if ( ( ptr[0x1fe] != 0x55 ) || ( ptr[0x1ff] != 0xaa ) )
\r
609 return F_ERR_NOTFORMATTED; /*??*/
\r
612 if ( ( ptr[0] != 0xeb ) && ( ptr[0] != 0xe9 ) )
\r
614 return F_ERR_NOTFORMATTED; /*??*/
\r
619 if ( _f_getword( ptr ) != F_SECTOR_SIZE )
\r
621 return F_ERR_NOTSUPPSECTORSIZE;
\r
625 gl_volume.bootrecord.sector_per_cluster = *ptr++;
\r
626 gl_volume.firstfat.sector = _f_getword( ptr );
\r
628 gl_volume.bootrecord.number_of_FATs = *ptr++;
\r
629 gl_volume.root.num = _f_getword( ptr );
\r
631 gl_volume.root.num *= sizeof( F_DIRENTRY );
\r
632 gl_volume.root.num /= F_SECTOR_SIZE;
\r
633 maxcluster = _f_getword( ptr );
\r
635 gl_volume.bootrecord.media_descriptor = *ptr++;
\r
636 gl_volume.firstfat.num = _f_getword( ptr );
\r
638 _n = _f_getlong( ptr );
\r
640 if ( _n < first_sector )
\r
645 gl_volume.firstfat.sector += _n;
\r
648 maxcluster = _f_getlong( ptr );
\r
654 if ( gl_volume.firstfat.num )
\r
656 gl_volume.root.sector = gl_volume.firstfat.sector + ( gl_volume.firstfat.num * gl_volume.bootrecord.number_of_FATs );
\r
657 gl_volume._tdata.sector = gl_volume.root.sector + gl_volume.root.num;
\r
658 gl_volume._tdata.num = 0;
\r
663 gl_volume.firstfat.num = _f_getlong( ptr );
\r
665 gl_volume._tdata.sector = gl_volume.firstfat.sector;
\r
666 gl_volume._tdata.sector += gl_volume.firstfat.num * gl_volume.bootrecord.number_of_FATs;
\r
667 gl_volume._tdata.num = 0;
\r
668 gl_volume.bootrecord.rootcluster = _f_getlong( ptr );
\r
670 gl_volume.root.num = gl_volume.bootrecord.sector_per_cluster;
\r
671 gl_volume.root.sector = ( ( gl_volume.bootrecord.rootcluster - 2 ) * gl_volume.root.num ) + gl_volume._tdata.sector;
\r
674 gl_volume.bootrecord.serial_number = _f_getlong( ptr );
\r
676 maxcluster -= gl_volume._tdata.sector;
\r
678 gl_volume.maxcluster = maxcluster / gl_volume.bootrecord.sector_per_cluster;
\r
680 if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xfff ) )
\r
682 gl_volume.mediatype = F_FAT12_MEDIA;
\r
684 else if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xffff ) )
\r
686 gl_volume.mediatype = F_FAT16_MEDIA;
\r
690 gl_volume.mediatype = F_FAT32_MEDIA;
\r
693 if ( gl_volume.bootrecord.media_descriptor != 0xf8 ) /*fixdrive*/
\r
695 if ( gl_volume.bootrecord.media_descriptor != 0xf0 ) /*removable*/
\r
697 return F_ERR_NOTFORMATTED; /*??*/
\r
702 } /* _f_readbootrecord */
\r
707 /****************************************************************************
\r
711 * getting back a volume info structure of a given drive, it try to mounts
\r
712 * drive if it was not mounted before
\r
716 * error code or zero if successful
\r
718 ***************************************************************************/
\r
719 unsigned char _f_getvolume ( void )
\r
721 switch ( gl_volume.state )
\r
724 return F_ERR_ONDRIVE;
\r
726 case F_STATE_WORKING:
\r
728 if ( !_f_checkstatus() )
\r
733 /* here we don't stop case flow, */
\r
734 /* because we have to clean up this volume! */
\r
736 case F_STATE_NEEDMOUNT:
\r
738 gl_file.modified = 0;
\r
739 gl_volume.modified = 0;
\r
740 gl_volume.lastalloccluster = 0;
\r
741 gl_volume.actsector = (unsigned long)( -1 );
\r
742 gl_volume.fatsector = (unsigned long)( -1 );
\r
744 gl_file.mode = F_FILE_CLOSE;
\r
746 gl_volume.cwd[0] = 0; /*reset cwd*/
\r
747 gl_volume.mediatype = F_UNKNOWN_MEDIA;
\r
749 if ( mdrv->getstatus != NULL )
\r
751 if ( mdrv->getstatus( mdrv ) & F_ST_MISSING )
\r
753 gl_volume.state = F_STATE_NEEDMOUNT; /*card missing*/
\r
754 return F_ERR_CARDREMOVED;
\r
758 if ( !_f_readbootrecord() )
\r
760 gl_volume.state = F_STATE_WORKING;
\r
764 gl_volume.mediatype = F_UNKNOWN_MEDIA;
\r
765 return F_ERR_NOTFORMATTED;
\r
769 return F_ERR_ONDRIVE;
\r
770 } /* _f_getvolume */
\r
774 /****************************************************************************
\r
778 * get total/free/used/bad diskspace
\r
781 * pspace - pointer where to store the information
\r
786 ***************************************************************************/
\r
787 unsigned char fn_getfreespace ( F_SPACE * pspace )
\r
791 unsigned long clustersize;
\r
793 ret = _f_getvolume();
\r
799 psp_memset( pspace, 0, sizeof( F_SPACE ) );
\r
800 pspace->total = gl_volume.maxcluster;
\r
802 gl_volume.fatsector = (unsigned long)-1;
\r
803 for ( a = 2 ; a < gl_volume.maxcluster + 2 ; a++ )
\r
805 unsigned long value;
\r
807 ret = _f_getclustervalue( a, &value );
\r
815 ++( pspace->free );
\r
817 else if ( value == F_CLUSTER_BAD )
\r
823 ++( pspace->used );
\r
827 clustersize = (unsigned long)( gl_volume.bootrecord.sector_per_cluster * F_SECTOR_SIZE );
\r
828 for ( a = 0 ; ( clustersize & 1 ) == 0 ; a++ )
\r
833 pspace->total_high = ( pspace->total ) >> ( 32 - a );
\r
834 pspace->total <<= a;
\r
835 pspace->free_high = ( pspace->free ) >> ( 32 - a );
\r
836 pspace->free <<= a;
\r
837 pspace->used_high = ( pspace->used ) >> ( 32 - a );
\r
838 pspace->used <<= a;
\r
839 pspace->bad_high = ( pspace->bad ) >> ( 32 - a );
\r
843 } /* fn_getfreespace */
\r
846 /****************************************************************************
\r
850 * get serial number
\r
853 * serial - pointer where to store the serial number
\r
858 ***************************************************************************/
\r
859 unsigned char fn_getserial ( unsigned long * serial )
\r
863 ret = _f_getvolume();
\r
869 *serial = gl_volume.bootrecord.serial_number;
\r
877 ** Initialize STHIN file system
\r
879 ** RETURN: F_NO_ERROR on success, other if error.
\r
881 unsigned char fs_init ( void )
\r
883 unsigned char rc = F_NO_ERROR;
\r
900 ** Delete STHIN file system
\r
902 ** RETURN: F_NO_ERROR on success, other if error.
\r
904 unsigned char fs_delete ( void )
\r
906 unsigned char rc = F_NO_ERROR;
\r
920 /****************************************************************************
\r
924 * initiate a volume, this function has to be called 1st to set physical
\r
925 * driver function to a given volume
\r
929 * error code or zero if successful
\r
931 ***************************************************************************/
\r
932 unsigned char fn_initvolume ( F_DRIVERINIT initfunc )
\r
934 #if F_FS_THREAD_AWARE == 1
\r
936 extern xSemaphoreHandle fs_lock_semaphore;
\r
938 if( fs_lock_semaphore == NULL )
\r
940 fs_lock_semaphore = xSemaphoreCreateMutex();
\r
941 if( fs_lock_semaphore == NULL )
\r
947 #endif /* F_FS_THREAD_AWARE */
\r
949 gl_volume.state = F_STATE_NONE;
\r
951 mdrv = initfunc( 0 );
\r
952 if ( mdrv == NULL )
\r
954 return F_ERR_INITFUNC;
\r
957 gl_volume.state = F_STATE_NEEDMOUNT;
\r
959 #if F_FILE_CHANGED_EVENT
\r
960 f_filechangedevent = 0;
\r
963 return _f_getvolume();
\r
964 } /* fn_initvolume */
\r
967 /****************************************************************************
\r
971 ***************************************************************************/
\r
972 unsigned char fn_delvolume ( void )
\r
974 if ( mdrv->release )
\r
976 (void)mdrv->release( mdrv );
\r