SAM4S-EK_FreeRTOS+FAT-SL  1.0
An example project to test the functionality of FreeRTOS+FAT-SL using SD card as data storage medium
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
volume.c
Go to the documentation of this file.
1 /*
2  * FreeRTOS+FAT SL V1.0.1 (C) 2014 HCC Embedded
3  *
4  * The FreeRTOS+FAT SL license terms are different to the FreeRTOS license
5  * terms.
6  *
7  * FreeRTOS+FAT SL uses a dual license model that allows the software to be used
8  * under a standard GPL open source license, or a commercial license. The
9  * standard GPL license (unlike the modified GPL license under which FreeRTOS
10  * itself is distributed) requires that all software statically linked with
11  * FreeRTOS+FAT SL is also distributed under the same GPL V2 license terms.
12  * Details of both license options follow:
13  *
14  * - Open source licensing -
15  * FreeRTOS+FAT SL is a free download and may be used, modified, evaluated and
16  * distributed without charge provided the user adheres to version two of the
17  * GNU General Public License (GPL) and does not remove the copyright notice or
18  * this text. The GPL V2 text is available on the gnu.org web site, and on the
19  * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.
20  *
21  * - Commercial licensing -
22  * Businesses and individuals who for commercial or other reasons cannot comply
23  * with the terms of the GPL V2 license must obtain a commercial license before
24  * incorporating FreeRTOS+FAT SL into proprietary software for distribution in
25  * any form. Commercial licenses can be purchased from
26  * http://shop.freertos.org/fat_sl and do not require any source files to be
27  * changed.
28  *
29  * FreeRTOS+FAT SL is distributed in the hope that it will be useful. You
30  * cannot use FreeRTOS+FAT SL unless you agree that you use the software 'as
31  * is'. FreeRTOS+FAT SL is provided WITHOUT ANY WARRANTY; without even the
32  * implied warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
33  * PARTICULAR PURPOSE. Real Time Engineers Ltd. and HCC Embedded disclaims all
34  * conditions and terms, be they implied, expressed, or statutory.
35  *
36  * http://www.FreeRTOS.org
37  * http://www.FreeRTOS.org/FreeRTOS-Plus
38  *
39  */
40 
41 #include "fat_sl.h"
42 #include "psp_string.h"
43 
44 #include "volume.h"
45 #include "util.h"
46 #include "drv.h"
47 #include "fat.h"
48 #include "dir.h"
49 #include "file.h"
50 
51 #include "../../version/ver_fat_sl.h"
52 #if VER_FAT_SL_MAJOR != 5 || VER_FAT_SL_MINOR != 2
53  #error Incompatible FAT_SL version number!
54 #endif
55 
56 #if F_FS_THREAD_AWARE == 1
57  #include "f_lock.h"
58 #endif
59 
60 F_VOLUME gl_volume; /* only one volume */
61 F_FILE gl_file; /* file */
62 char gl_sector[F_SECTOR_SIZE]; /* actual sector */
63 
64 #if F_FILE_CHANGED_EVENT
65 F_FILE_CHANGED_EVENTFUNC f_filechangedevent;
66 #endif
67 
68 
69 /* Defines the number of sectors per cluster on a sector number basis */
70 typedef struct
71 {
72  unsigned long max_sectors;
73  unsigned char sector_per_cluster;
74 } t_FAT32_CS;
75 
76 static const t_FAT32_CS FAT32_CS[] =
77 {
78  { 0x00020000, 1 } /* ->64MB */
79  , { 0x00040000, 2 } /* ->128MB */
80  , { 0x00080000, 4 } /* ->256MB */
81  , { 0x01000000, 8 } /* ->8GB */
82  , { 0x02000000, 16 } /* ->16GB */
83  , { 0x0ffffff0, 32 } /* -> ... */
84 };
85 
86 
87 /****************************************************************************
88  *
89  * _f_writebootrecord
90  *
91  * writing boot record onto a volume, it uses number of hidden sector variable
92  *
93  * INPUTS
94  * phy - media physical descriptor
95  *
96  * RETURNS
97  * error code or zero if successful
98  *
99  ***************************************************************************/
100 static unsigned char _f_writebootrecord ( F_PHY * phy )
101 {
102  unsigned char jump_code[] =
103  {
104  0xeb, 0x3c, 0x90
105  };
106  unsigned char oem_name[] = "MSDOS5.0";
107  unsigned char executable_marker[] =
108  {
109  0x55, 0xaa
110  };
111  unsigned char * ptr = (unsigned char *)gl_sector;
112  unsigned char rs;
113  unsigned short mre;
114 
115  unsigned char ret;
116  unsigned char _n = 0;
117 
118  if ( gl_volume.mediatype == F_FAT32_MEDIA )
119  { /*write FS_INFO*/
120  unsigned char a;
121 
122  rs = 32 + 4;
123  mre = 0;
124 
125  psp_memset( ptr, 0, F_SECTOR_SIZE );
126 
127  for ( a = 0 ; a < rs ; a++ )
128  {
129  ret = _f_writeglsector( a ); /*erase reserved area*/
130  if ( ret )
131  {
132  return ret;
133  }
134  }
135 
136  ptr = _setlong( 0x41615252, ptr ); /*signature*/
137  ptr = _setcharzero( 480, ptr ); /*reserved*/
138  ptr = _setlong( 0x61417272, ptr ); /*signature*/
139  ptr = _setlong( 0xffffffff, ptr ); /*no last*/
140  ptr = _setlong( 0xffffffff, ptr ); /*no hint*/
141  ptr = _setcharzero( 12, ptr ); /*reserved*/
142  ptr = _setlong( 0xaa550000, ptr ); /*trail*/
143 
144 
145  ret = _f_writeglsector( 1 ); /*write FSINFO*/
146  if ( ret )
147  {
148  return ret;
149  }
150 
151  ret = _f_writeglsector( 1 + 6 ); /*write FSINFO*/
152  if ( ret )
153  {
154  return ret;
155  }
156  }
157  else
158  {
159  rs = 1;
160  mre = 512;
161  }
162 
163  ptr = (unsigned char *)gl_sector;
164  ptr = _setchar( jump_code, sizeof( jump_code ), ptr );
165  ptr = _setchar( oem_name, sizeof( oem_name ) - 1, ptr );
166  ptr = _setword( F_SECTOR_SIZE, ptr );
167  *ptr++ = gl_volume.bootrecord.sector_per_cluster;
168  ptr = _setword( rs, ptr ); /* reserved sectors */
169  *ptr++ = 2; /* number of FATs */
170  ptr = _setword( mre, ptr ); /* max root entry */
171  if ( phy->number_of_sectors < 0x10000 )
172  {
173  ptr = _setword( (unsigned short)phy->number_of_sectors, ptr );
174  }
175  else
176  {
177  ptr = _setword( 0, ptr );
178  }
179 
180  *ptr++ = 0xf0; /* media descriptor */
181  ptr = _setword( (unsigned short)gl_volume.bootrecord.sector_per_FAT, ptr );
182  ptr = _setword( phy->sector_per_track, ptr );
183  ptr = _setword( phy->number_of_heads, ptr );
184  ptr = _setlong( 0, ptr ); /* number of hidden sectors */
185  if ( phy->number_of_sectors >= 0x10000 )
186  {
187  ptr = _setlong( phy->number_of_sectors, ptr );
188  }
189  else
190  {
191  ptr = _setlong( 0, ptr ); /* number of sectors */
192  }
193 
194  if ( gl_volume.mediatype == F_FAT32_MEDIA )
195  {
196  ptr = _setlong( gl_volume.bootrecord.sector_per_FAT32, ptr );
197  ptr = _setword( 0, ptr );
198  ptr = _setword( 0, ptr );
199  ptr = _setlong( 2, ptr );
200  ptr = _setword( 1, ptr );
201  ptr = _setword( 6, ptr );
202  ptr = _setchar( NULL, 12, ptr );
203  _n = 28;
204  }
205 
206 
207  ptr = _setword( 0, ptr ); /* logical drive num */
208  *ptr++ = 0x29; /* extended signature */
209  ptr = _setlong( 0x11223344, ptr );
210  ptr = _setchar( (const unsigned char *)"NO NAME ", 11, ptr ); /* volume name */
211 
212  switch ( gl_volume.mediatype )
213  {
214  case F_FAT12_MEDIA:
215  ptr = _setchar( (const unsigned char *)"FAT12 ", 8, ptr );
216  break;
217 
218  case F_FAT16_MEDIA:
219  ptr = _setchar( (const unsigned char *)"FAT16 ", 8, ptr );
220  break;
221 
222  case F_FAT32_MEDIA:
223  ptr = _setchar( (const unsigned char *)"FAT32 ", 8, ptr );
224  break;
225 
226  default:
227  return F_ERR_INVALIDMEDIA;
228  } /* switch */
229 
230  ptr = _setchar( 0, 448 - _n, ptr );
231  ptr = _setchar( executable_marker, sizeof( executable_marker ), ptr );
232 
233  if ( _n )
234  {
235  ret = _f_writeglsector( 6 );
236  if ( ret )
237  {
238  return ret;
239  }
240  }
241 
242 
243  return _f_writeglsector( 0 ); /*write bootrecord*/
244 } /* _f_writebootrecord */
245 
246 
247 /****************************************************************************
248  *
249  * _f_buildsectors
250  *
251  * INPUTS
252  * phy - media physical descriptor
253  *
254  * calculate relative sector position from boot record
255  *
256  ***************************************************************************/
257 static unsigned char _f_buildsectors ( F_PHY * phy )
258 {
259  gl_volume.mediatype = F_UNKNOWN_MEDIA;
260 
261 
262  if ( gl_volume.bootrecord.sector_per_FAT )
263  {
264  gl_volume.firstfat.sector = 1;
265  gl_volume.firstfat.num = gl_volume.bootrecord.sector_per_FAT;
266  gl_volume.root.sector = gl_volume.firstfat.sector + ( gl_volume.firstfat.num * (unsigned long)( gl_volume.bootrecord.number_of_FATs ) );
267  gl_volume.root.num = ( 512 * sizeof( F_DIRENTRY ) ) / F_SECTOR_SIZE;
268 
269  gl_volume._tdata.sector = gl_volume.root.sector + gl_volume.root.num;
270  gl_volume._tdata.num = 0; /*??*/
271  }
272  else
273  {
274  gl_volume.firstfat.sector = ( 32 + 4 );
275  gl_volume.firstfat.num = gl_volume.bootrecord.sector_per_FAT32;
276  gl_volume._tdata.sector = gl_volume.firstfat.sector;
277  gl_volume._tdata.sector += gl_volume.firstfat.num * (unsigned long)( gl_volume.bootrecord.number_of_FATs );
278  gl_volume._tdata.num = 0; /*??*/
279 
280  {
281  unsigned long sectorcou = gl_volume.bootrecord.sector_per_cluster;
282  gl_volume.root.sector = ( ( gl_volume.bootrecord.rootcluster - 2 ) * sectorcou ) + gl_volume._tdata.sector;
283  gl_volume.root.num = gl_volume.bootrecord.sector_per_cluster;
284  }
285  }
286 
287  {
288  unsigned long maxcluster;
289  maxcluster = phy->number_of_sectors;
290  maxcluster -= gl_volume._tdata.sector;
291  maxcluster /= gl_volume.bootrecord.sector_per_cluster;
292  gl_volume.maxcluster = maxcluster;
293  }
294 
295  if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xfff ) )
296  {
297  gl_volume.mediatype = F_FAT12_MEDIA;
298  }
299  else if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xffff ) )
300  {
301  gl_volume.mediatype = F_FAT16_MEDIA;
302  }
303  else
304  {
305  gl_volume.mediatype = F_FAT32_MEDIA;
306  }
307 
308  return F_NO_ERROR;
309 } /* _f_buildsectors */
310 
311 
312 
313 /****************************************************************************
314  *
315  * _f_prepareformat
316  *
317  * preparing boot record for formatting, it sets and calculates values
318  *
319  * INPUTS
320  * phy - media physical descriptor
321  * f_bootrecord - which bootrecord need to be prepare
322  * number_of_hidden_sectors - where boot record starts
323  * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA
324  *
325  * RETURNS
326  * error code or zero if successful
327  *
328  ***************************************************************************/
329 static unsigned char _f_prepareformat ( F_PHY * phy, unsigned char fattype )
330 {
331  if ( !phy->number_of_sectors )
332  {
333  return F_ERR_INVALIDSECTOR;
334  }
335 
336  gl_volume.bootrecord.number_of_FATs = 2;
337  gl_volume.bootrecord.media_descriptor = 0xf0;
338 
339  if ( fattype != F_FAT32_MEDIA )
340  {
341  unsigned long _n;
342  switch ( fattype )
343  {
344  case F_FAT12_MEDIA:
345  _n = F_CLUSTER_RESERVED & 0xfff;
346  break;
347 
348  case F_FAT16_MEDIA:
349  _n = F_CLUSTER_RESERVED & 0xffff;
350  break;
351 
352  default:
353  return F_ERR_INVFATTYPE;
354  }
355 
356  gl_volume.bootrecord.sector_per_cluster = 1;
357  while ( gl_volume.bootrecord.sector_per_cluster )
358  {
359  if ( phy->number_of_sectors / gl_volume.bootrecord.sector_per_cluster < _n )
360  {
361  break;
362  }
363 
364  gl_volume.bootrecord.sector_per_cluster <<= 1;
365  }
366 
367  if ( !gl_volume.bootrecord.sector_per_cluster )
368  {
369  return F_ERR_MEDIATOOLARGE;
370  }
371  }
372 
373  else
374  {
375  unsigned char i;
376  for ( i = 0 ; i<( sizeof( FAT32_CS ) / sizeof( t_FAT32_CS ) ) - 1 && phy->number_of_sectors>FAT32_CS[i].max_sectors ; i++ )
377  {
378  }
379 
380  gl_volume.bootrecord.sector_per_cluster = FAT32_CS[i].sector_per_cluster;
381  }
382 
383  if ( !gl_volume.bootrecord.sector_per_cluster )
384  {
385  return F_ERR_INVALIDMEDIA; /*fat16 cannot be there*/
386  }
387 
388  {
389  long secpercl = gl_volume.bootrecord.sector_per_cluster;
390  long nfat = gl_volume.bootrecord.number_of_FATs;
391  unsigned long roots;
392  unsigned long fatsec;
393 
394  roots = ( 512 * sizeof( F_DIRENTRY ) ) / F_SECTOR_SIZE;
395 
396  switch ( fattype )
397  {
398  case F_FAT32_MEDIA:
399  {
400  unsigned long _n = (unsigned long)( 128 * secpercl + nfat );
401  fatsec = ( phy->number_of_sectors - ( 32 + 4 ) + 2 * secpercl );
402  fatsec += ( _n - 1 );
403  fatsec /= _n;
404  gl_volume.bootrecord.sector_per_FAT32 = fatsec;
405  gl_volume.bootrecord.sector_per_FAT = 0;
406  }
407  break;
408 
409  case F_FAT16_MEDIA:
410  {
411  unsigned long _n = (unsigned long)( 256 * secpercl + nfat );
412  fatsec = ( phy->number_of_sectors - 1 - roots + 2 * secpercl );
413  fatsec += ( _n - 1 );
414  fatsec /= _n;
415  gl_volume.bootrecord.sector_per_FAT = (unsigned short)( fatsec );
416  }
417  break;
418 
419  case F_FAT12_MEDIA:
420  {
421  unsigned long _n = (unsigned long)( 1024 * secpercl + 3 * nfat );
422  fatsec = ( phy->number_of_sectors - 1 - roots + 2 * secpercl );
423  fatsec *= 3;
424  fatsec += ( _n - 1 );
425  fatsec /= _n;
426  gl_volume.bootrecord.sector_per_FAT = (unsigned short)( fatsec );
427  }
428  break;
429 
430  default:
431  return F_ERR_INVALIDMEDIA;
432  } /* switch */
433 
434  return F_NO_ERROR;
435  }
436 } /* _f_prepareformat */
437 
438 
439 
440 /****************************************************************************
441  *
442  * _f_postformat
443  *
444  * erase fats, erase root directory, reset variables after formatting
445  *
446  * INPUTS
447  * phy - media physical descriptor
448  * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA
449  *
450  * RETURNS
451  * error code or zero if successful
452  *
453  ***************************************************************************/
454 static unsigned char _f_postformat ( F_PHY * phy, unsigned char fattype )
455 {
456  unsigned long a;
457  unsigned char ret;
458 
459  _f_buildsectors( phy ); /*get positions*/
460  if ( gl_volume.mediatype != fattype )
461  {
462  return F_ERR_MEDIATOOSMALL;
463  }
464 
465  gl_volume.fatsector = (unsigned long)( -1 );
466 
467  {
468  unsigned char * ptr = (unsigned char *)gl_sector;
469  unsigned char j = 2;
470  unsigned long i;
471 
472  psp_memset( ptr, 0, F_SECTOR_SIZE );
473 
474  switch ( gl_volume.mediatype )
475  {
476  case F_FAT16_MEDIA:
477  j = 3;
478  break;
479 
480  case F_FAT32_MEDIA:
481  j = 11;
482  break;
483  }
484 
485  *ptr = gl_volume.bootrecord.media_descriptor;
486  psp_memset( ptr + 1, 0xff, j );
487  if ( gl_volume.mediatype == F_FAT32_MEDIA )
488  {
489  *( ptr + 8 ) = (unsigned char)( F_CLUSTER_LAST & 0xff );
490  }
491 
492  (void)_f_writeglsector( gl_volume.firstfat.sector );
493  (void)_f_writeglsector( gl_volume.firstfat.sector + gl_volume.firstfat.num );
494  psp_memset( ptr, 0, ( j + 1 ) );
495 
496  for ( i = 1 ; i < gl_volume.firstfat.num ; i++ )
497  {
498  (void)_f_writeglsector( gl_volume.firstfat.sector + i );
499  (void)_f_writeglsector( gl_volume.firstfat.sector + i + gl_volume.firstfat.num );
500  }
501  }
502 
503  for ( a = 0 ; a < gl_volume.root.num ; a++ ) /*reset root direntries*/
504  {
505  ret = _f_writeglsector( gl_volume.root.sector + a );
506  if ( ret )
507  {
508  return ret;
509  }
510  }
511 
512  return _f_writebootrecord( phy );
513 } /* _f_postformat */
514 
515 
516 /****************************************************************************
517  *
518  * fn_hardformat
519  *
520  * Making a complete format on media, independently from master boot record,
521  * according to media physical
522  *
523  * INPUTS
524  * fattype - one of this definitions F_FAT12_MEDIA,F_FAT16_MEDIA,F_FAT32_MEDIA
525  *
526  * RETURNS
527  * error code or zero if successful
528  *
529  ***************************************************************************/
530 unsigned char fn_hardformat ( unsigned char fattype )
531 {
532  unsigned char ret;
533  int mdrv_ret;
534  F_PHY phy;
535 
536  ret = _f_getvolume();
537  if ( ret && ( ret != F_ERR_NOTFORMATTED ) )
538  {
539  return ret;
540  }
541 
542  gl_volume.state = F_STATE_NEEDMOUNT;
543 
544  psp_memset( &phy, 0, sizeof( F_PHY ) );
545 
546  mdrv_ret = mdrv->getphy( mdrv, &phy );
547  if ( mdrv_ret )
548  {
549  return F_ERR_ONDRIVE;
550  }
551 
552  ret = _f_prepareformat( &phy, fattype ); /*no partition*/
553  if ( ret )
554  {
555  return ret;
556  }
557 
558  return _f_postformat( &phy, fattype );
559 } /* fn_hardformat */
560 
561 
562 
563 
564 /****************************************************************************
565  *
566  * _f_readbootrecord
567  *
568  * read boot record from a volume, it detects if there is MBR on the media
569  *
570  * RETURNS
571  *
572  * error code or zero if successful
573  *
574  ***************************************************************************/
575 static unsigned char _f_readbootrecord ( void )
576 {
577  unsigned char ret;
578  unsigned char * ptr = (unsigned char *)gl_sector;
579  unsigned long maxcluster, _n;
580  unsigned long first_sector = 0;
581 
582  gl_volume.mediatype = F_UNKNOWN_MEDIA;
583 
584 
585  ret = _f_readglsector( 0 );
586  if ( ret )
587  {
588  return ret;
589  }
590 
591 
592  if ( ( ptr[0x1fe] != 0x55 ) || ( ptr[0x1ff] != 0xaa ) )
593  {
594  return F_ERR_NOTFORMATTED; /*??*/
595  }
596 
597  if ( ( ptr[0] != 0xeb ) && ( ptr[0] != 0xe9 ) )
598  {
599  first_sector = _f_getlong( &ptr[0x08 + 0x1be] ); /*start sector for 1st partition*/
600 
601  ret = _f_readglsector( first_sector );
602  if ( ret )
603  {
604  return ret;
605  }
606 
607  if ( ( ptr[0x1fe] != 0x55 ) || ( ptr[0x1ff] != 0xaa ) )
608  {
609  return F_ERR_NOTFORMATTED; /*??*/
610  }
611 
612  if ( ( ptr[0] != 0xeb ) && ( ptr[0] != 0xe9 ) )
613  {
614  return F_ERR_NOTFORMATTED; /*??*/
615  }
616  }
617 
618  ptr += 11;
619  if ( _f_getword( ptr ) != F_SECTOR_SIZE )
620  {
622  }
623 
624  ptr += 2;
625  gl_volume.bootrecord.sector_per_cluster = *ptr++;
626  gl_volume.firstfat.sector = _f_getword( ptr );
627  ptr += 2;
628  gl_volume.bootrecord.number_of_FATs = *ptr++;
629  gl_volume.root.num = _f_getword( ptr );
630  ptr += 2;
631  gl_volume.root.num *= sizeof( F_DIRENTRY );
632  gl_volume.root.num /= F_SECTOR_SIZE;
633  maxcluster = _f_getword( ptr );
634  ptr += 2;
635  gl_volume.bootrecord.media_descriptor = *ptr++;
636  gl_volume.firstfat.num = _f_getword( ptr );
637  ptr += 6;
638  _n = _f_getlong( ptr );
639  ptr += 4;
640  if ( _n < first_sector )
641  {
642  _n = first_sector;
643  }
644 
645  gl_volume.firstfat.sector += _n;
646  if ( !maxcluster )
647  {
648  maxcluster = _f_getlong( ptr );
649  }
650 
651  ptr += 4;
652 
653 
654  if ( gl_volume.firstfat.num )
655  {
656  gl_volume.root.sector = gl_volume.firstfat.sector + ( gl_volume.firstfat.num * gl_volume.bootrecord.number_of_FATs );
657  gl_volume._tdata.sector = gl_volume.root.sector + gl_volume.root.num;
658  gl_volume._tdata.num = 0;
659  ptr += 3;
660  }
661  else
662  {
663  gl_volume.firstfat.num = _f_getlong( ptr );
664  ptr += 8;
665  gl_volume._tdata.sector = gl_volume.firstfat.sector;
666  gl_volume._tdata.sector += gl_volume.firstfat.num * gl_volume.bootrecord.number_of_FATs;
667  gl_volume._tdata.num = 0;
668  gl_volume.bootrecord.rootcluster = _f_getlong( ptr );
669  ptr += 23;
670  gl_volume.root.num = gl_volume.bootrecord.sector_per_cluster;
671  gl_volume.root.sector = ( ( gl_volume.bootrecord.rootcluster - 2 ) * gl_volume.root.num ) + gl_volume._tdata.sector;
672  }
673 
674  gl_volume.bootrecord.serial_number = _f_getlong( ptr );
675 
676  maxcluster -= gl_volume._tdata.sector;
677  maxcluster += _n;
678  gl_volume.maxcluster = maxcluster / gl_volume.bootrecord.sector_per_cluster;
679 
680  if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xfff ) )
681  {
682  gl_volume.mediatype = F_FAT12_MEDIA;
683  }
684  else if ( gl_volume.maxcluster < ( F_CLUSTER_RESERVED & 0xffff ) )
685  {
686  gl_volume.mediatype = F_FAT16_MEDIA;
687  }
688  else
689  {
690  gl_volume.mediatype = F_FAT32_MEDIA;
691  }
692 
693  if ( gl_volume.bootrecord.media_descriptor != 0xf8 ) /*fixdrive*/
694  {
695  if ( gl_volume.bootrecord.media_descriptor != 0xf0 ) /*removable*/
696  {
697  return F_ERR_NOTFORMATTED; /*??*/
698  }
699  }
700 
701  return F_NO_ERROR;
702 } /* _f_readbootrecord */
703 
704 
705 
706 
707 /****************************************************************************
708  *
709  * _f_getvolume
710  *
711  * getting back a volume info structure of a given drive, it try to mounts
712  * drive if it was not mounted before
713  *
714  * RETURNS
715  *
716  * error code or zero if successful
717  *
718  ***************************************************************************/
719 unsigned char _f_getvolume ( void )
720 {
721  switch ( gl_volume.state )
722  {
723  case F_STATE_NONE:
724  return F_ERR_ONDRIVE;
725 
726  case F_STATE_WORKING:
727 
728  if ( !_f_checkstatus() )
729  {
730  return F_NO_ERROR;
731  }
732 
733  /* here we don't stop case flow, */
734  /* because we have to clean up this volume! */
735 
736  case F_STATE_NEEDMOUNT:
737  {
738  gl_file.modified = 0;
739  gl_volume.modified = 0;
740  gl_volume.lastalloccluster = 0;
741  gl_volume.actsector = (unsigned long)( -1 );
742  gl_volume.fatsector = (unsigned long)( -1 );
743 
744  gl_file.mode = F_FILE_CLOSE;
745 
746  gl_volume.cwd[0] = 0; /*reset cwd*/
747  gl_volume.mediatype = F_UNKNOWN_MEDIA;
748 
749  if ( mdrv->getstatus != NULL )
750  {
751  if ( mdrv->getstatus( mdrv ) & F_ST_MISSING )
752  {
753  gl_volume.state = F_STATE_NEEDMOUNT; /*card missing*/
754  return F_ERR_CARDREMOVED;
755  }
756  }
757 
758  if ( !_f_readbootrecord() )
759  {
760  gl_volume.state = F_STATE_WORKING;
761  return F_NO_ERROR;
762  }
763 
764  gl_volume.mediatype = F_UNKNOWN_MEDIA;
765  return F_ERR_NOTFORMATTED;
766  }
767  } /* switch */
768 
769  return F_ERR_ONDRIVE;
770 } /* _f_getvolume */
771 
772 
773 
774 /****************************************************************************
775  *
776  * fn_getfreespace
777  *
778  * get total/free/used/bad diskspace
779  *
780  * INPUTS
781  * pspace - pointer where to store the information
782  *
783  * RETURNS
784  * error code
785  *
786  ***************************************************************************/
787 unsigned char fn_getfreespace ( F_SPACE * pspace )
788 {
789  unsigned char ret;
790  unsigned long a;
791  unsigned long clustersize;
792 
793  ret = _f_getvolume();
794  if ( ret )
795  {
796  return ret;
797  }
798 
799  psp_memset( pspace, 0, sizeof( F_SPACE ) );
800  pspace->total = gl_volume.maxcluster;
801 
802  gl_volume.fatsector = (unsigned long)-1;
803  for ( a = 2 ; a < gl_volume.maxcluster + 2 ; a++ )
804  {
805  unsigned long value;
806 
807  ret = _f_getclustervalue( a, &value );
808  if ( ret )
809  {
810  return ret;
811  }
812 
813  if ( !value )
814  {
815  ++( pspace->free );
816  }
817  else if ( value == F_CLUSTER_BAD )
818  {
819  ++( pspace->bad );
820  }
821  else
822  {
823  ++( pspace->used );
824  }
825  }
826 
827  clustersize = (unsigned long)( gl_volume.bootrecord.sector_per_cluster * F_SECTOR_SIZE );
828  for ( a = 0 ; ( clustersize & 1 ) == 0 ; a++ )
829  {
830  clustersize >>= 1;
831  }
832 
833  pspace->total_high = ( pspace->total ) >> ( 32 - a );
834  pspace->total <<= a;
835  pspace->free_high = ( pspace->free ) >> ( 32 - a );
836  pspace->free <<= a;
837  pspace->used_high = ( pspace->used ) >> ( 32 - a );
838  pspace->used <<= a;
839  pspace->bad_high = ( pspace->bad ) >> ( 32 - a );
840  pspace->bad <<= a;
841 
842  return F_NO_ERROR;
843 } /* fn_getfreespace */
844 
845 
846 /****************************************************************************
847  *
848  * fn_getserial
849  *
850  * get serial number
851  *
852  * INPUTS
853  * serial - pointer where to store the serial number
854  *
855  * RETURNS
856  * error code
857  *
858  ***************************************************************************/
859 unsigned char fn_getserial ( unsigned long * serial )
860 {
861  unsigned char ret;
862 
863  ret = _f_getvolume();
864  if ( ret )
865  {
866  return ret;
867  }
868 
869  *serial = gl_volume.bootrecord.serial_number;
870  return 0;
871 }
872 
873 
874 /*
875 ** fs_init
876 **
877 ** Initialize STHIN file system
878 **
879 ** RETURN: F_NO_ERROR on success, other if error.
880 */
881 unsigned char fs_init ( void )
882 {
883  unsigned char rc = F_NO_ERROR;
884 
885 #if RTOS_SUPPORT
886  rc = fsr_init();
887  if ( rc )
888  {
889  return rc;
890  }
891 
892 #endif
893  return rc;
894 } /* fs_init */
895 
896 
897 /*
898 ** fs_delete
899 **
900 ** Delete STHIN file system
901 **
902 ** RETURN: F_NO_ERROR on success, other if error.
903 */
904 unsigned char fs_delete ( void )
905 {
906  unsigned char rc = F_NO_ERROR;
907 
908 #if RTOS_SUPPORT
909  rc = fsr_delete();
910  if ( rc )
911  {
912  return rc;
913  }
914 
915 #endif
916  return rc;
917 } /* fs_delete */
918 
919 
920 /****************************************************************************
921  *
922  * fn_initvolume
923  *
924  * initiate a volume, this function has to be called 1st to set physical
925  * driver function to a given volume
926  *
927  * RETURNS
928  *
929  * error code or zero if successful
930  *
931  ***************************************************************************/
932 unsigned char fn_initvolume ( F_DRIVERINIT initfunc )
933 {
934 #if F_FS_THREAD_AWARE == 1
935  {
936  extern xSemaphoreHandle fs_lock_semaphore;
937 
938  if( fs_lock_semaphore == NULL )
939  {
940  fs_lock_semaphore = xSemaphoreCreateMutex();
941  if( fs_lock_semaphore == NULL )
942  {
943  return F_ERR_OS;
944  }
945  }
946  }
947 #endif /* F_FS_THREAD_AWARE */
948 
949  gl_volume.state = F_STATE_NONE;
950 
951  mdrv = initfunc( 0 );
952  if ( mdrv == NULL )
953  {
954  return F_ERR_INITFUNC;
955  }
956 
957  gl_volume.state = F_STATE_NEEDMOUNT;
958 
959 #if F_FILE_CHANGED_EVENT
960  f_filechangedevent = 0;
961 #endif
962 
963  return _f_getvolume();
964 } /* fn_initvolume */
965 
966 
967 /****************************************************************************
968  *
969  * fn_delvolume
970  *
971  ***************************************************************************/
972 unsigned char fn_delvolume ( void )
973 {
974  if ( mdrv->release )
975  {
976  (void)mdrv->release( mdrv );
977  }
978 
979  return 0;
980 }
unsigned long bad_high
Definition: fat_sl.h:207
unsigned long sector
Definition: volume.h:70
unsigned char modified
Definition: volume.h:87
unsigned char fsr_delete(void)
unsigned char fs_init(void)
Definition: volume.c:881
unsigned long sector_per_FAT
Definition: volume.h:62
unsigned long used
Definition: fat_sl.h:201
F_SECTOR firstfat
Definition: volume.h:79
unsigned long free
Definition: fat_sl.h:200
#define xSemaphoreHandle
Definition: FreeRTOS.h:731
unsigned long fatsector
Definition: volume.h:84
unsigned long actsector
Definition: volume.h:83
unsigned char sector_per_cluster
Definition: volume.c:73
unsigned long max_sectors
Definition: volume.c:72
unsigned char fn_initvolume(F_DRIVERINIT initfunc)
Definition: volume.c:932
unsigned long serial_number
Definition: volume.h:64
F_GETPHY getphy
Definition: api_mdriver.h:91
F_VOLUME gl_volume
Definition: volume.c:60
F_BOOTRECORD bootrecord
Definition: volume.h:78
unsigned char * _setlong(unsigned long, unsigned char *)
Definition: util.c:254
F_FILE gl_file
Definition: volume.c:61
unsigned char sector_per_cluster
Definition: volume.h:58
unsigned long sector_per_FAT32
Definition: volume.h:63
unsigned char fsr_init(void)
unsigned long _f_getlong(void *)
Definition: util.c:116
unsigned long lastalloccluster
Definition: volume.h:86
char cwd[F_MAXPATH]
Definition: volume.h:88
char gl_sector[F_SECTOR_SIZE]
Definition: volume.c:62
unsigned char * _setcharzero(int, unsigned char *)
Definition: util.c:171
unsigned long used_high
Definition: fat_sl.h:206
unsigned char _f_writeglsector(unsigned long sector)
Definition: drv.c:96
unsigned long total
Definition: fat_sl.h:199
unsigned short _f_getword(void *)
Definition: util.c:68
unsigned char mode
Definition: fat_sl.h:114
unsigned char fn_getfreespace(F_SPACE *pspace)
Definition: volume.c:787
Definition: dir.h:75
F_DRIVER *(* F_DRIVERINIT)(unsigned long driver_param)
Definition: api_mdriver.h:96
unsigned long number_of_sectors
Definition: api_mdriver.h:59
unsigned char mediatype
Definition: volume.h:89
unsigned char modified
Definition: fat_sl.h:113
unsigned long free_high
Definition: fat_sl.h:205
unsigned long total_high
Definition: fat_sl.h:204
#define F_SECTOR_SIZE
Definition: config_fat_sl.h:57
#define F_FILE_CLOSE
Definition: file.h:53
#define psp_memset(d, c, l)
Definition: psp_string.h:54
F_DRIVER * mdrv
Definition: drv.c:53
unsigned char fn_hardformat(unsigned char fattype)
Definition: volume.c:530
#define F_CLUSTER_BAD
Definition: fat_sl.h:99
F_SECTOR _tdata
Definition: volume.h:81
unsigned long num
Definition: volume.h:71
unsigned char * _setchar(const unsigned char *, int, unsigned char *)
Definition: util.c:199
F_SECTOR root
Definition: volume.h:80
#define F_CLUSTER_LAST
Definition: fat_sl.h:100
unsigned char _f_getvolume(void)
Definition: volume.c:719
unsigned char media_descriptor
Definition: volume.h:60
unsigned long maxcluster
Definition: volume.h:90
unsigned char number_of_FATs
Definition: volume.h:59
unsigned long bad
Definition: fat_sl.h:202
unsigned char * _setword(unsigned short, unsigned char *)
Definition: util.c:231
unsigned char fs_delete(void)
Definition: volume.c:904
unsigned char _f_readglsector(unsigned long sector)
Definition: drv.c:178
F_RELEASE release
Definition: api_mdriver.h:93
unsigned long rootcluster
Definition: volume.h:61
#define F_CLUSTER_RESERVED
Definition: fat_sl.h:98
unsigned char _f_getclustervalue(unsigned long cluster, unsigned long *pvalue)
Definition: fat.c:302
unsigned char fn_getserial(unsigned long *serial)
Definition: volume.c:859
#define F_ST_MISSING
Definition: api_mdriver.h:70
unsigned char fn_delvolume(void)
Definition: volume.c:972
Definition: fat_sl.h:107
unsigned char state
Definition: volume.h:77
unsigned short number_of_heads
Definition: api_mdriver.h:58
unsigned char _f_checkstatus(void)
Definition: drv.c:67
#define xSemaphoreCreateMutex()
Definition: semphr.h:689
F_GETSTATUS getstatus
Definition: api_mdriver.h:92
unsigned short sector_per_track
Definition: api_mdriver.h:57