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
40 #include "../../api/fat_sl.h"
\r
47 #include "../../version/ver_fat_sl.h"
\r
48 #if VER_FAT_SL_MAJOR != 5 || VER_FAT_SL_MINOR != 2
\r
49 #error Incompatible FAT_SL version number!
\r
52 /****************************************************************************
\r
56 * writing fat sector into volume, this function check if fat was modified
\r
61 * error code or zero if successful
\r
63 ***************************************************************************/
\r
64 unsigned char _f_writefatsector ( void )
\r
68 if ( gl_volume.modified )
\r
70 unsigned long fatsector = gl_volume.firstfat.sector + gl_volume.fatsector;
\r
72 if ( gl_volume.fatsector >= gl_volume.firstfat.num )
\r
74 return F_ERR_INVALIDSECTOR;
\r
77 for ( a = 0 ; a < gl_volume.bootrecord.number_of_FATs ; a++ )
\r
80 ret = _f_writeglsector( fatsector );
\r
86 fatsector += gl_volume.firstfat.num;
\r
89 gl_volume.modified = 0;
\r
93 } /* _f_writefatsector */
\r
97 /****************************************************************************
\r
101 * read a fat sector from media
\r
105 * sector - which fat sector is needed, this sector number is zero based
\r
109 * error code or zero if successful
\r
111 ***************************************************************************/
\r
112 unsigned char _f_getfatsector ( unsigned long sector )
\r
116 if ( gl_volume.fatsector != sector )
\r
118 unsigned long fatsector;
\r
120 gl_volume.fatsector = sector;
\r
122 if ( gl_volume.fatsector >= gl_volume.firstfat.num )
\r
124 return F_ERR_INVALIDSECTOR;
\r
127 fatsector = gl_volume.firstfat.sector + gl_volume.fatsector;
\r
129 for ( a = 0 ; a < gl_volume.bootrecord.number_of_FATs ; a++ )
\r
131 if ( !_f_readglsector( fatsector ) )
\r
136 fatsector += gl_volume.firstfat.num;
\r
143 } /* _f_getfatsector */
\r
147 /****************************************************************************
\r
149 * _f_setclustervalue
\r
151 * set a cluster value in the FAT
\r
155 * cluster - which cluster's value need to be modified
\r
156 * data - new value of the cluster
\r
160 * error code or zero if successful
\r
162 ***************************************************************************/
\r
163 unsigned char _f_setclustervalue ( unsigned long cluster, unsigned long _tdata )
\r
167 switch ( gl_volume.mediatype )
\r
169 case F_FAT16_MEDIA:
\r
171 unsigned long sector = cluster;
\r
172 unsigned short s_data = (unsigned short)( _tdata & 0xffff ); /*keep 16 bit only*/
\r
174 sector /= ( F_SECTOR_SIZE / 2 );
\r
175 cluster -= sector * ( F_SECTOR_SIZE / 2 );
\r
177 ret = _f_getfatsector( sector );
\r
183 if ( _f_getword( &gl_sector[cluster << 1] ) != s_data )
\r
185 _f_setword( &gl_sector[cluster << 1], s_data );
\r
186 gl_volume.modified = 1;
\r
191 case F_FAT12_MEDIA:
\r
193 unsigned char f12new[2];
\r
194 unsigned long sector = cluster;
\r
195 unsigned short pos;
\r
196 unsigned short s_data = (unsigned short)( _tdata & 0x0fff ); /*keep 12 bit only*/
\r
203 _f_setword( f12new, s_data ); /*create new data*/
\r
205 sector += sector / 2; /*1.5 bytes*/
\r
206 pos = (unsigned short)( sector % F_SECTOR_SIZE );
\r
207 sector /= F_SECTOR_SIZE;
\r
209 ret = _f_getfatsector( sector );
\r
217 f12new[0] |= gl_sector[pos] & 0x0f;
\r
220 if ( gl_sector[pos] != f12new[0] )
\r
222 gl_sector[pos] = f12new[0];
\r
223 gl_volume.modified = 1;
\r
229 ret = _f_getfatsector( sector + 1 );
\r
238 if ( !( cluster & 1 ) )
\r
240 f12new[1] |= gl_sector[pos] & 0xf0;
\r
243 if ( gl_sector[pos] != f12new[1] )
\r
245 gl_sector[pos] = f12new[1];
\r
246 gl_volume.modified = 1;
\r
251 case F_FAT32_MEDIA:
\r
253 unsigned long sector = cluster;
\r
254 unsigned long oldv;
\r
256 sector /= ( F_SECTOR_SIZE / 4 );
\r
257 cluster -= sector * ( F_SECTOR_SIZE / 4 );
\r
259 ret = _f_getfatsector( sector );
\r
265 oldv = _f_getlong( &gl_sector[cluster << 2] );
\r
267 _tdata &= 0x0fffffff;
\r
268 _tdata |= oldv & 0xf0000000; /*keep 4 top bits*/
\r
270 if ( _tdata != oldv )
\r
272 _f_setlong( &gl_sector[cluster << 2], _tdata );
\r
273 gl_volume.modified = 1;
\r
279 return F_ERR_INVALIDMEDIA;
\r
283 } /* _f_setclustervalue */
\r
286 /****************************************************************************
\r
288 * _f_getclustervalue
\r
290 * get a cluster value from FAT
\r
294 * cluster - which cluster value is requested
\r
295 * pvalue - where to store data
\r
299 * error code or zero if successful
\r
301 ***************************************************************************/
\r
302 unsigned char _f_getclustervalue ( unsigned long cluster, unsigned long * pvalue )
\r
307 switch ( gl_volume.mediatype )
\r
309 case F_FAT16_MEDIA:
\r
311 unsigned long sector = cluster;
\r
312 sector /= ( F_SECTOR_SIZE / 2 );
\r
313 cluster -= sector * ( F_SECTOR_SIZE / 2 );
\r
315 ret = _f_getfatsector( sector );
\r
321 val = _f_getword( &gl_sector[cluster << 1] );
\r
322 if ( val >= ( F_CLUSTER_RESERVED & 0xffff ) )
\r
324 val |= 0x0ffff000; /*extends it*/
\r
334 case F_FAT12_MEDIA:
\r
336 unsigned char dataf12[2];
\r
337 unsigned long sector = cluster;
\r
338 unsigned short pos;
\r
340 sector += sector / 2; /*1.5 bytes*/
\r
341 pos = (unsigned short)( sector % F_SECTOR_SIZE );
\r
342 sector /= F_SECTOR_SIZE;
\r
344 ret = _f_getfatsector( sector );
\r
350 dataf12[0] = gl_sector[pos++];
\r
354 ret = _f_getfatsector( sector + 1 );
\r
363 dataf12[1] = gl_sector[pos];
\r
365 val = _f_getword( dataf12 );
\r
376 if ( val >= ( F_CLUSTER_RESERVED & 0xfff ) )
\r
378 val |= 0x0ffff000; /*extends it*/
\r
388 case F_FAT32_MEDIA:
\r
390 unsigned long sector = cluster;
\r
391 sector /= ( F_SECTOR_SIZE / 4 );
\r
392 cluster -= sector * ( F_SECTOR_SIZE / 4 );
\r
394 ret = _f_getfatsector( sector );
\r
402 *pvalue = _f_getlong( &gl_sector[cluster << 2] ) & 0x0fffffff; /*28bit*/
\r
408 return F_ERR_INVALIDMEDIA;
\r
412 } /* _f_getclustervalue */
\r
419 /****************************************************************************
\r
423 * convert a cluster position into physical sector position
\r
427 * cluster - original cluster position
\r
428 * pos - position structure to fills the position
\r
430 ***************************************************************************/
\r
431 void _f_clustertopos ( unsigned long cluster, F_POS * pos )
\r
433 pos->cluster = cluster;
\r
437 pos->sector = gl_volume.root.sector;
\r
438 pos->sectorend = pos->sector + gl_volume.root.num;
\r
442 unsigned long sectorcou = gl_volume.bootrecord.sector_per_cluster;
\r
443 pos->sector = ( pos->cluster - 2 ) * sectorcou + gl_volume._tdata.sector;
\r
444 pos->sectorend = pos->sector + sectorcou;
\r
447 if ( cluster >= F_CLUSTER_RESERVED )
\r
449 pos->sectorend = 0;
\r
453 } /* _f_clustertopos */
\r
458 /****************************************************************************
\r
462 * read current sector according in file structure
\r
465 * f - internal file pointer
\r
468 * error code or zero if successful
\r
470 ***************************************************************************/
\r
471 unsigned char _f_getcurrsector ( void )
\r
474 unsigned long cluster;
\r
476 if ( gl_file.pos.sector == gl_file.pos.sectorend )
\r
478 gl_volume.fatsector = (unsigned long)-1;
\r
479 ret = _f_getclustervalue( gl_file.pos.cluster, &cluster );
\r
485 if ( cluster >= F_CLUSTER_RESERVED )
\r
490 _f_clustertopos( cluster, &gl_file.pos );
\r
493 return _f_readglsector( gl_file.pos.sector );
\r
494 } /* _f_getcurrsector */
\r
498 /****************************************************************************
\r
502 * allocate cluster from FAT
\r
505 * pcluster - where to store the allocated cluster number
\r
509 * error code or zero if successful
\r
511 ***************************************************************************/
\r
512 unsigned char _f_alloccluster ( unsigned long * pcluster )
\r
514 unsigned long maxcluster = gl_volume.maxcluster;
\r
516 unsigned long cluster = gl_volume.lastalloccluster;
\r
517 unsigned long value;
\r
520 for ( cou = 0 ; cou < maxcluster ; cou++ )
\r
522 if ( cluster >= maxcluster )
\r
527 ret = _f_getclustervalue( cluster, &value );
\r
535 gl_volume.lastalloccluster = cluster + 1; /*set next one*/
\r
536 *pcluster = cluster;
\r
544 return F_ERR_NOMOREENTRY;
\r
545 } /* _f_alloccluster */
\r
550 /****************************************************************************
\r
554 * remove cluster chain from fat
\r
557 * cluster - first cluster in the cluster chain
\r
561 * error code or zero if successful
\r
563 ***************************************************************************/
\r
564 unsigned char _f_removechain ( unsigned long cluster )
\r
566 gl_volume.fatsector = (unsigned long)-1;
\r
568 if ( cluster < gl_volume.lastalloccluster ) /*this could be the begining of alloc*/
\r
570 gl_volume.lastalloccluster = cluster;
\r
573 while ( cluster < F_CLUSTER_RESERVED && cluster >= 2 )
\r
575 unsigned long nextcluster;
\r
577 unsigned char ret = _f_getclustervalue( cluster, &nextcluster );
\r
583 ret = _f_setclustervalue( cluster, F_CLUSTER_FREE );
\r
589 cluster = nextcluster;
\r
592 return _f_writefatsector();
\r
593 } /* _f_removechain */
\r