source: soft/giet_vm/giet_fat32/fat32.c @ 561

Last change on this file since 561 was 551, checked in by alain, 9 years ago

Move the L2/L3 cache coherence from the fat_ioc_access() function to the HBA and BDV drivers.

  • Property svn:executable set to *
File size: 64.9 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : fat32.c
3// Date     : 01/09/2013
4// Authors  : Marco Jankovic, Cesar Fuguet & Alain Greiner
5// Copyright (c) UPMC-LIP6
6//////////////////////////////////////////////////////////////////////////////////
7// The fat.h and fat_common.c files define a library of access functions
8// to a FAT32 disk on a block device. It is intended to be used
9// by the GIET_VM nano-kernel for both the boot code and the kernel code.
10//////////////////////////////////////////////////////////////////////////////////
11// Implementation notes:
12// 1. the "lba" (Logical Block Address) is the physical sector index on
13//    the block device. The physical sector size is supposed to be 512 bytes.
14// 2. the "cluster" variable is actually a cluster index. A cluster contains
15//    typically 8 sectors (4K bytes) and the cluster index is a 32 bits word.
16// 3. This FAT32 library uses a FAT cache whose storage capacity is one
17//    sector (512 bytes = 128 cluster indexes in FAT)
18//////////////////////////////////////////////////////////////////////////////////
19
20#include <giet_config.h>
21#include <hard_config.h>
22#include <fat32.h>
23#include <utils.h>
24#include <vmem.h>
25#include <bdv_driver.h>
26#include <hba_driver.h>
27#include <sdc_driver.h>
28#include <rdk_driver.h>
29#include <mmc_driver.h>
30#include <tty0.h>
31
32//////////////////////////////////////////////////////////////////////////////////
33//      Global variable : internal FAT representation
34//////////////////////////////////////////////////////////////////////////////////
35
36extern fat32_fs_t _fat;
37
38extern unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
39 
40//////////////////////////////////////////////////////////////////////////////
41// This function computes the memory buffer physical address, and calls
42// the proper IOC driver depending on the subtype (BDV / HBA / SDC /RDK).
43// The use_irq argument allows to activate the descheduling mode, if it
44// supported by the IOC driver subtype
45//////////////////////////////////////////////////////////////////////////////
46// Return 0 in case of success, return -1 in case of error
47//////////////////////////////////////////////////////////////////////////////
48static
49int _fat_ioc_access( unsigned int use_irq,
50                     unsigned int to_mem,
51                     unsigned int lba,
52                     unsigned int buf_vaddr,
53                     unsigned int count ) 
54{
55    // compute memory buffer physical address
56    unsigned int       flags;         // for _v2p_translate
57    unsigned long long buf_paddr;     // buffer physical address
58
59    if ( ((_get_mmu_mode() & 0x4) == 0 ) || USE_IOC_RDK )  // identity
60    {
61        buf_paddr = (unsigned long long)buf_vaddr;
62    }
63    else                                // V2P translation required
64    {
65        buf_paddr = _v2p_translate( buf_vaddr , &flags );
66    }
67
68#if (GIET_DEBUG_FAT > 1)
69unsigned int procid  = _get_procid();
70unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
71unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
72unsigned int p       = procid & ((1<<P_WIDTH)-1);
73_printf("\n[DEBUG FAT] P[%d,%d,%d] enters _fat_ioc_access() at cycle %d\n"
74        "  to_mem = %d / vaddr = %x / paddr = %l / sectors = %d / lba = %x\n",
75        x, y , p, _get_proctime(), to_mem, buf_vaddr, buf_paddr, count, lba );
76#endif
77
78
79#if GIET_NO_HARD_CC     // L1 cache inval (virtual addresses)
80    if ( to_mem ) _dcache_buf_invalidate( buf_vaddr, count<<9 );
81#endif
82
83
84#if   ( USE_IOC_BDV )   // call the proper driver
85    return( _bdv_access( use_irq , to_mem , lba , buf_paddr , count ) ); 
86#elif ( USE_IOC_HBA )
87    return( _hba_access( use_irq , to_mem , lba , buf_paddr , count ) );
88#elif ( USE_IOC_SPI )
89    return( _sdc_access( use_irq , to_mem , lba , buf_paddr , count ) );
90#elif ( USE_IOC_RDK )
91    return( _rdk_access( use_irq , to_mem , lba , buf_paddr , count ) );
92#else
93    _printf("\n[FAT ERROR] in _fat_ioc_access() : no IOC driver\n");
94    _exit();
95#endif
96
97}  // end _fat_ioc_access()
98
99
100//////////////////////////////////////////////////////////////////////////////////
101// This function displays the content of the FAT cache
102//////////////////////////////////////////////////////////////////////////////////
103#if (GIET_DEBUG_FAT > 1)
104static
105void _display_fat_cache()
106{
107    unsigned int line;
108    unsigned int word;
109    unsigned int temp[9];
110
111    temp[8] = 0;
112
113    _puts("\n*********************** fat_cache_lba = ");
114    _putx( _fat.cache_lba );
115    _puts(" *****************************\n");
116
117    for ( line = 0 ; line < 16 ; line++ )
118    {
119        // display line index
120        _putx( line );
121        _puts(" : ");
122
123        // display 8*4 bytes hexa
124        for ( word=0 ; word<8 ; word++ )
125        {
126            unsigned int byte  = (line<<5) + (word<<2);
127            unsigned int hexa  = (_fat.fat_cache[byte  ]<<24) |
128                                 (_fat.fat_cache[byte+1]<<16) |
129                                 (_fat.fat_cache[byte+2]<< 8) |
130                                 (_fat.fat_cache[byte+3]);
131            _putx( hexa );
132            _puts(" | ");
133
134            // prepare display ascii
135            temp[word] = _fat.fat_cache[byte]         |
136                         (_fat.fat_cache[byte+1]<<8)  |
137                         (_fat.fat_cache[byte+2]<<16) |
138                         (_fat.fat_cache[byte+3]<<24) ;
139        }
140       
141        // display data ascii
142        _puts( (char*)temp );
143        _puts("\n");
144    }
145    _puts("***************************************************************************\n");
146
147} // end _display_fat_cache() 
148#endif
149
150//////////////////////////////////////////////////////////////////////////////////
151// This function displays the FAT descriptor.
152//////////////////////////////////////////////////////////////////////////////////
153#if GIET_DEBUG_FAT
154static
155void _fat_print()
156{
157    _printf("\n########################## FAT32 ################################" 
158            "\nFAT initialised                  %x"
159            "\nSector Size  (bytes)             %x"
160            "\nSectors per cluster              %x"
161            "\nFAT region first lba             %x"
162            "\nData region first lba            %x"
163            "\nNumber of sectors for one FAT    %x"
164            "\nNumber of free clusters          %x"
165            "\nLast allocated cluster           %x" 
166            "\n#################################################################\n",
167            _fat.initialised,
168            _fat.sector_size,
169            _fat.sectors_per_cluster,
170            _fat.fat_lba,
171            _fat.data_lba,
172            _fat.fat_sectors,
173            _fat.number_free_cluster,
174            _fat.last_cluster_allocated );
175} // end _fat_print()
176#endif
177
178//////////////////////////////////////////////////////////////////////////////////
179// This function returns the length of a FAT field. This field is identified
180// by an (offset,length) mnemonic defined in fat32.h file.
181//////////////////////////////////////////////////////////////////////////////////
182static inline 
183int get_length( int offset, 
184                int length )
185{
186    return length;
187}
188
189//////////////////////////////////////////////////////////////////////////////
190// Write one 32 bits word "value" in a char[] buffer.
191// The modified field in buffer is defined by the offset and size arguments.
192//////////////////////////////////////////////////////////////////////////////
193static 
194void _write_entry( unsigned int   offset,
195                   unsigned int   size,
196                   char*          buffer,
197                   unsigned int   value )
198{
199    unsigned int turn = 0;
200    unsigned int res  = value;
201    unsigned int mask = 0x000000ff;
202
203    while( turn != size - 1 )
204    {
205        buffer[ offset + turn ] = res & mask;
206        res = res >> 8;
207        turn++;
208    }
209    buffer[offset + turn] = res & mask;
210}
211
212//////////////////////////////////////////////////////////////////////////////
213// Read one 32 bits word in a char[] buffer, taking endianness into account.
214// The analysed field in buffer is defined by the offset and size arguments.
215//////////////////////////////////////////////////////////////////////////////
216static 
217unsigned int _read_entry( unsigned int   offset,
218                          unsigned int   size,
219                          char*          buffer,
220                          unsigned int   little_indian )
221{
222    unsigned int turn;
223    unsigned int res  = 0;
224    unsigned int mask = 0x000000ff;
225
226    if( little_indian )
227    {
228        turn = size;
229        while( turn != 1 )
230        {
231            res = res | (buffer[offset + (turn-1)] & mask);
232            res = res << 8;
233            turn--;
234        }
235        res = (buffer[offset + (turn-1)] & mask) | res;
236    }
237    else
238    {
239        turn = 0;
240        while( turn != size - 1 )
241        {
242
243            res = res  | (buffer[ offset + turn ] & mask );
244            res = res << 8;
245            turn++;
246        }
247        res = res | (buffer[offset + turn] & mask);
248    }
249    return res;
250}
251
252//////////////////////////////////////////////////////////////////////////////////
253// This function retuns the cluster index from the lba of a DATA sector.
254// The lba must be larger than the lba of the first DATA sector.
255// The DATA region indexing starts a cluster 2.
256//////////////////////////////////////////////////////////////////////////////////
257static inline 
258unsigned int lba_to_cluster( unsigned int lba )                   
259{
260   if (lba < _fat.data_lba ) return 0;
261
262   return ( (lba - _fat.data_lba) / _fat.sectors_per_cluster) + 2; 
263}
264
265//////////////////////////////////////////////////////////////////////////////////
266// This function retuns the lba of first sector in DATA region
267// from the cluster index. The cluster index must be larger than 2.
268//////////////////////////////////////////////////////////////////////////////////
269static inline 
270unsigned int cluster_to_lba( unsigned int cluster )       
271{
272   if ( cluster < 2 ) return 0; 
273
274   return  (_fat.sectors_per_cluster * (cluster - 2)) + _fat.data_lba;
275}
276
277/////////////////////////////////////////////////////////////////////////////////
278// This function search the FAT (using the FAT cache), and returns
279// the next cluster index from the current cluster index in the FAT.
280// remark: a sector of FAT contains 128 cluster indexes.
281/////////////////////////////////////////////////////////////////////////////////
282static 
283unsigned int _get_next_cluster( unsigned int use_irq,
284                                unsigned int cluster )
285{
286    // compute lba of the sector containing the cluster index
287    unsigned int lba = _fat.fat_lba + (cluster / 128);
288
289    if ( lba != _fat.cache_lba )      // miss in fat_cache
290    {
291        // access fat
292        if( _fat_ioc_access( use_irq,
293                             1,               // read
294                             lba, 
295                             (unsigned int)_fat.fat_cache,
296                             1 ) )            // one sector
297        {
298            _printf("[FAT_ERROR] in get_next_cluster_id() : cannot read block %x", 
299                    lba );
300            return 1;
301        }
302        _fat.cache_lba = lba;
303    }
304
305    unsigned int next = _read_entry( ((cluster % 128) * 4), 
306                                     4, 
307                                     _fat.fat_cache,
308                                     1 );
309#if (GIET_DEBUG_FAT > 1)
310unsigned int procid  = _get_procid();
311unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
312unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
313unsigned int p       = procid & ((1<<P_WIDTH)-1);
314_printf("\n[DEBUG FAT] P[%d,%d,%d] in _get_next_cluster() :  next = %x\n",
315        x , y , p , next );
316_display_fat_cache();
317#endif
318
319    return next;
320}
321
322//////////////////////////////////////////////////////
323static inline unsigned char to_upper(unsigned char c)
324{
325   if (c >= 'a' && c <= 'z') return (c & ~(0x20));
326   else                      return c;
327}
328
329////////////////////////////////////////////////////////////////
330// This function is a filter:
331// Return the c character if c is a legal short name character
332// Return the '_' character if c is illegal
333////////////////////////////////////////////////////////////////
334static 
335unsigned char illegal_short(unsigned char c)
336{
337   const unsigned char illegal_char [] =";+=[]’,\"*\\<>/?:|\0";
338   short i = 0;
339   while (illegal_char[i]!='\0')
340   {
341      if (c == illegal_char[i])
342         return '_';
343      i++;
344   }
345   return c;
346}
347
348/////////////////////////////////////////////////////////////////////////////////
349// This function test if the string argument is a legal SFN (Short File Name)
350// and copies this name (removing the .) in the sfn_string argument.
351// Criteria for a Short File Name are:
352// - separator is '.' (extension is not mandatory)
353// - 1 <= name length <= 8
354// - 0 <= extension length <= 3
355// - no illegal character (see illega_short() function)
356// Return 1 if it string is a legal SFN
357// Return 0 if not legal SFN
358/////////////////////////////////////////////////////////////////////////////////
359static 
360int is_short( char* string, 
361              char* sfn_string)
362{
363    int s_size   = 0;
364    int dot_ext  = 0;       // dot offset in the filename
365    int name_len = 0;       // length of file name
366    int ext_len  = 0;       // length of extension
367    int i        = 0;
368    int sc_i     = 0;
369    char ch;
370
371    if(string[0] == '.' && string[1] == '\0')
372    {
373        sfn_string[0] = '.';
374        return 1;
375    }
376    if(string[0] == '.' && string[1] == '.' && string[2] == '\0')
377    {
378        sfn_string[0] = '.';
379        sfn_string[1] = '.';
380        return 1;
381    }
382    sfn_string[11] = '\0';
383    while (string[s_size] != '\0')
384    {
385        if (string[s_size] == '.')
386        {
387            dot_ext = s_size;
388            ext_len = -1;
389        }
390        ext_len++;
391        s_size++;
392    }
393    if (dot_ext != 0)
394    {
395        name_len = s_size - ext_len - 1;
396    }
397    else
398    {
399        name_len = s_size;
400        ext_len = 0;
401    }
402    if ( ext_len > 3 || ( name_len > 8))
403    {
404        return 0;
405    }
406    if (dot_ext != 0)
407    {
408        while (i != ext_len)
409        {
410            ch = to_upper(string[dot_ext + 1 + i]);
411            ch = illegal_short(ch);
412            sfn_string[8+i] = ch;
413            i++;
414        } 
415    }
416    i = 0;
417    sc_i = 0;
418    while (i!= name_len)
419    {
420        ch = to_upper(string[i]);
421        ch = illegal_short(ch);
422        if (ch != '.') sfn_string[sc_i++] = ch;
423        i++;
424    }
425    return 1;
426}
427
428///////////////////////////////////////////////////////////////////////
429// This function analyses the pathname argument, from the character
430// defined by the *nb_read argument.
431// It copies the found name (between '/') in the name[] buffer,
432// and updates the nb_read argument.
433// Return 1 if name found, Return 0 if NUL character found,
434///////////////////////////////////////////////////////////////////////
435static 
436int get_name_from_path( char*          pathname,
437                        char*          name,
438                        unsigned int*  nb_read )       
439{
440    if ( pathname[*nb_read] == 0 ) return 0;
441
442    int i = (pathname[*nb_read] == '/')? (*nb_read) + 1 : *nb_read;
443    int j = 0;
444   
445    while(pathname[i] != '/' && pathname[i] != '\0')
446    {
447        name[j] = pathname[i];   
448        j++;
449        i++;
450    }
451    name[j] = 0;
452
453    if ( pathname[i] == '/' ) *nb_read += j+1;
454    else                      *nb_read += j;
455
456    return 1;
457}
458
459////////////////////////////////////////////////////////////////////////////////
460static int get_name_from_short( char* dir_entry,     // input:  SFN dir_entry
461                                char* entry_name )   // output: name
462{
463    unsigned int i   = 0;
464    unsigned int length = get_length(DIR_NAME);
465
466    while ( i < length )
467    {
468        entry_name[i] = dir_entry[i];
469        i++;
470    }
471    entry_name[i] = '\0';
472
473    return i;
474}
475
476///////////////////////////////////////////////////////////////////////////////
477static int get_name_from_long( char *dir_entry,     // input : LFN dir_entry
478                               char *entry_name )   // output : name
479{
480    unsigned int   entry_name_offset   = 0;
481    unsigned int   dir_entry_offset    = get_length(LDIR_ORD);
482    unsigned int   l_name_1            = get_length(LDIR_NAME_1);
483    unsigned int   l_name_2            = get_length(LDIR_NAME_2);
484    unsigned int   l_name_3            = get_length(LDIR_NAME_3);
485    unsigned int   l_attr              = get_length(LDIR_ATTR);
486    unsigned int   l_type              = get_length(LDIR_TYPE);
487    unsigned int   l_chksum            = get_length(LDIR_CHKSUM);
488    unsigned int   l_rsvd              = get_length(LDIR_RSVD);
489
490    unsigned int j            = 0;
491    unsigned int eof          = 0;
492
493    while ( (dir_entry_offset != DIR_ENTRY_SIZE)  && (!eof) )
494    {
495        while (j != l_name_1 && !eof )
496        {
497            if ( (dir_entry[dir_entry_offset] == 0x00) || 
498                 (dir_entry[dir_entry_offset] == 0xFF) )
499            {
500                eof = 1;
501                continue;
502            }
503            entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
504            dir_entry_offset += 2;
505            j += 2;
506            entry_name_offset++;
507        }
508
509        dir_entry_offset += (l_attr + l_type + l_chksum);
510        j = 0;
511
512        while (j != l_name_2 && !eof )
513        {
514            if ( (dir_entry[dir_entry_offset] == 0x00) || 
515                 (dir_entry[dir_entry_offset] == 0xFF) )
516            {
517                eof = 1;
518                continue;
519            }
520            entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
521            dir_entry_offset += 2;
522            j += 2;
523            entry_name_offset++;
524        }
525
526        dir_entry_offset += l_rsvd;
527        j = 0;
528
529        while (j != l_name_3 && !eof )
530        {
531            if ( (dir_entry[dir_entry_offset] == 0x00) || 
532                 (dir_entry[dir_entry_offset] == 0xFF) )
533            {
534                eof = 1;
535                continue;
536            }
537            entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
538            dir_entry_offset += 2;
539            j += 2;
540            entry_name_offset++;
541        }
542    }
543    entry_name[entry_name_offset] = '\0';
544
545    return entry_name_offset;
546} // end get_name_from_long()
547
548///////////////////////////////////////////////////////////////////////////////////
549// This function update a DIR_ENTRY, write a new value into a specific field
550// (ex : DIR_FILE_SIZE, when we want update the file size after a fat_write)
551// Return 0 in case of success, > 0 if failure.
552///////////////////////////////////////////////////////////////////////////////////
553// TODO : make this function less complex
554///////////////////////////////////////////////////////////////////////////////////
555static inline 
556unsigned int _update_entry( unsigned int use_irq,
557                            unsigned int fd_id, 
558                            unsigned int field,
559                            unsigned int size,
560                            unsigned int value )
561{
562    char dir_entry[32];   // buffer to store a full directory_entry
563    char name_entry[14];  // buffer to store a 13 characters (partial) name
564    char file_name[256];  // buffer to store the name (not pathname) of the file
565
566    char sfn_string[12]  = {[0 ... 10] = ' ', '\0'};     // buffer Short File Name
567    unsigned int lba     = _fat.fd[fd_id].lba_dir_entry;  // Lba of file dir_entry
568    unsigned int is_sfn;         
569    unsigned int attr    = 0;                            // dir entry attribute
570    unsigned int ord     = 0;                            // dir entry sequence
571    unsigned int found   = 0;                            // name found
572    unsigned int offset  = 0;                            // offset in fat_cache
573    unsigned int i       = 0;
574    unsigned int nb_read = 0;
575
576    for ( i = 0 ; i < 32 ; i++ ) dir_entry[i]  = 0;
577    for ( i = 0 ; i < 14 ; i++ ) name_entry[i] = 0;
578   
579    // Get the name of the file.
580    while ( get_name_from_path( _fat.fd[fd_id].name, file_name, &nb_read ) )
581    {
582    }
583
584    // Format file_name to SFN format
585    is_sfn = is_short( file_name, sfn_string );
586
587    // access FAT
588    if ( _fat_ioc_access( use_irq,
589                          1,               // read
590                          lba, 
591                          (unsigned int)_fat.fat_cache,
592                          1 ) )            // one sector
593    {
594        _printf("\n[FAT ERROR] in _update_entry() cannot read sector %x\n", 
595                lba );
596        return 1;
597    }
598    _fat.cache_lba = lba;
599
600    // - the offset increment is an integer number of directory entry (32 bytes)
601    // - the exit condition is success (name found) or failure (end of directory)
602    while ( !found )
603    {
604        attr = _read_entry( DIR_ATTR, _fat.fat_cache + offset, 0 );
605        ord  = _read_entry( LDIR_ORD, _fat.fat_cache + offset, 0 );
606
607        if ( is_sfn == 1 )                                     // searched name is short
608        {
609            if      ( (ord != FREE_ENTRY ) &&
610                    (ord != NO_MORE_ENTRY) &&
611                    (attr == ATTR_LONG_NAME_MASK) )    // LFN entry : skipped
612            {
613                offset     = offset + ((ord & 0xF) * DIR_ENTRY_SIZE);
614                continue;
615            }
616            else if ( (attr != ATTR_LONG_NAME_MASK) && 
617                    (ord  != FREE_ENTRY) && 
618                    (ord  != NO_MORE_ENTRY ) )         // SFN entry : checked
619            {
620                memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );   
621            }
622            else if (ord == NO_MORE_ENTRY )            // end of directory : return
623            {
624                _printf("\n[FAT ERROR] in _update_entry() : reaches end\n");
625                return 1;
626            }
627            else                                                                           // free entry : skipped
628            {
629                offset = offset + DIR_ENTRY_SIZE;
630                continue;
631            }
632        }
633        else                                           // searched name is long
634        {
635            if      ( (attr == ATTR_LONG_NAME_MASK) && 
636                    (ord != FREE_ENTRY) &&
637                    (ord != NO_MORE_ENTRY) )           // LFN entry : checked
638            {
639                memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );   
640            }
641            else if ( (attr != ATTR_LONG_NAME_MASK) && 
642                    (ord  != FREE_ENTRY) && 
643                    (ord  != NO_MORE_ENTRY))               // SFN entry : skipped
644            {
645                offset = offset + DIR_ENTRY_SIZE;
646                continue;
647            }
648            else if (ord == NO_MORE_ENTRY )                        // end of directory : return
649            {
650                _printf("\n[FAT ERROR] in _update_entry() reaches end\n");
651                return 1;
652            }
653            else                                       // free entry : skipped
654            {
655                offset = offset + DIR_ENTRY_SIZE;
656                continue;
657            }
658        }
659
660        // testing the name extracted from dir entry
661
662        if ( is_sfn == 1 )                             // searched name is short
663        {
664            get_name_from_short( dir_entry, name_entry );
665
666            if ( _strncmp( (char*)sfn_string, (char*)name_entry, 13 ) == 0 )
667            {
668                _write_entry(offset + field, size, _fat.fat_cache, value);
669                found = 1;
670            }
671            else                                                                       // no matching : skip
672            {
673                offset = offset + DIR_ENTRY_SIZE;
674            }
675        }
676        else                                           // searched name is long
677        {
678            get_name_from_long( dir_entry, name_entry );
679
680            unsigned shift = ((ord & 0xf) - 1) * 13;
681            if ( _strncmp( (char*)(file_name + shift), 
682                           (char*)name_entry, 13 ) == 0 )
683            {
684                if ( (ord & 0xf) == 1 )
685                {
686                    offset = offset + DIR_ENTRY_SIZE;
687                    _write_entry(offset + field, size, _fat.fat_cache, value);
688                    found = 1;
689                }
690                offset = offset + DIR_ENTRY_SIZE;
691                continue;
692            }
693            else                                                                       // no matching : skip
694            {
695                offset = offset + ((ord & 0xf) * DIR_ENTRY_SIZE) + DIR_ENTRY_SIZE;
696            }
697        }
698    }
699
700    // write block to FAT
701    if ( _fat_ioc_access( use_irq,
702                          0,                // write
703                          lba, 
704                          (unsigned int)_fat.fat_cache, 
705                          1 ) )             // one sector
706    {
707        _printf("\n[FAT ERROR] in _update_entry() cannot write sector %x\n", 
708                lba );
709        return 1;
710    }
711
712    return 0;
713} // end _update_entry()
714
715
716//////////////////////////////////////////////////////////////////////////////////
717// This function update the FS_INFO block:
718// last cluster allocated and number of free cluster.
719// Return 0 in case of success, > 0 if failure.
720//////////////////////////////////////////////////////////////////////////////////
721static inline 
722unsigned int _update_fs_info( unsigned int use_irq )
723{
724    unsigned int lba = _fat.fs_info_lba;
725
726#if GIET_DEBUG_FAT
727_printf("\n[DEBUG FAT] _update_fs_info()\n");
728#endif
729
730    // update FAT cache in case of miss
731    if ( lba != _fat.cache_lba )
732    {
733        if ( _fat_ioc_access( use_irq,
734                              1,                 // read
735                              lba, 
736                              (unsigned int)_fat.fat_cache, 
737                              1 ) )              // one sector
738        {
739            _printf("\n[FAT_ERROR] in _update_fs_info() cannot read block\n");
740            return 1;
741        }
742        _fat.cache_lba = lba;
743    }
744
745    _write_entry( FS_FREE_CLUSTER     , _fat.fat_cache, _fat.number_free_cluster );
746    _write_entry( FS_FREE_CLUSTER_HINT, _fat.fat_cache, _fat.last_cluster_allocated );
747   
748    // write bloc to FAT
749    if ( _fat_ioc_access( use_irq,
750                          0,                // write
751                          lba,
752                          (unsigned int)_fat.fat_cache, 
753                          1 ) )             // one sector
754    {
755        _printf("\n[FAT_ERROR] in _update_fs_info() cannot write block\n");
756        return 1;
757    }
758
759    return 0;
760}  // end _update_fs_info()
761
762//////////////////////////////////////////////////////////////////////////////////
763// This function update FAT, write a new value into cluster index.
764// Used by the function _fat_allocate to update the chaining of clusters.
765// Return 0 in case of success, > 0 if failure.
766//////////////////////////////////////////////////////////////////////////////////
767static inline 
768unsigned int _update_fat( unsigned int use_irq,
769                          unsigned int cluster, 
770                          unsigned int value  )
771{
772    unsigned int lba = _fat.fat_lba + (cluster / 128);
773
774#if GIET_DEBUG_FAT
775_printf("\n[DEBUG FAT] _update_fat() : cluster = %x / value = %x\n", 
776        cluster, value );
777#endif
778
779    // update FAT cache in case of miss
780    if ( lba != _fat.cache_lba ) 
781    {
782        if ( _fat_ioc_access( use_irq,
783                              1,                 // read
784                              lba, 
785                              (unsigned int)_fat.fat_cache, 
786                              1 ) )              // one sector
787        {
788            _printf("\n[FAT_ERROR] in _update_fat() cannot read block %x\n",
789                    lba );
790            return 1;
791        }
792        _fat.cache_lba = lba;
793    }
794
795    _write_entry( ((cluster % 128) << 2), 4, _fat.fat_cache, value );
796
797    // write bloc to FAT
798    if ( _fat_ioc_access( use_irq,
799                          0,                // write
800                          lba,
801                          (unsigned int)_fat.fat_cache,
802                          1 ) )             // one sector
803    {
804        _printf("\n[FAT_ERROR] in _update_fat() cannot write block %x\n",
805                lba );
806        return 1;
807    }
808
809    return 0;
810} // end update_fat()
811
812//////////////////////////////////////////////////////////////////////////////////
813// This function allocate count clusters to a file by calling the
814// _update_fat function that takes care to update the chaining of clusters.
815// return 0 if success, -1 if failure
816//////////////////////////////////////////////////////////////////////////////////
817static inline 
818int _fat_allocate( unsigned int use_irq,
819                   unsigned int fd_id, 
820                   unsigned int count )
821{
822    unsigned int next_cluster = _fat.fd[fd_id].first_cluster;    // first cluster
823    unsigned int cluster_to_allocate = count;                   // to allocate
824    unsigned int last_cluster_file;                             // Last cluster
825    unsigned int free_cluster = _fat.last_cluster_allocated + 1; // First free
826
827    // Check if free_cluster is really free (must be true)
828    if ( _get_next_cluster( use_irq , free_cluster ) != FREE_CLUSTER)
829    {
830        _printf("\n[FAT ERROR] in _fat_allocate() : first free cluster not free\n");
831        return -1;
832    }
833    // Check if FAT contains enough cluster free for this allocation
834    if ( count > _fat.number_free_cluster )
835    {
836        _printf("\n[FAT ERROR] in _fat_allocate() : Not enough free cluster(s)\n");
837        return -1;
838    }
839
840#if GIET_DEBUG_FAT
841_printf("\n[DEBUG FAT] _fat_allocate() for fd = %d\n", fd_id );
842#endif
843
844    // Get the last cluster allocated for the file (seek END_OF_CHAIN_CLUSTER).
845    do 
846    {
847        last_cluster_file = next_cluster;
848        next_cluster      = _get_next_cluster( use_irq , next_cluster );
849    }
850    while ( next_cluster < END_OF_CHAIN_CLUSTER );
851
852    // Loop on the number of clusters to be allocated
853    while ( cluster_to_allocate > 0 )
854    {
855
856#if GIET_DEBUG_FAT
857_printf("\n[DEBUG FAT] cluster to update = %x / free cluster = %x / count = %d\n",
858        last_cluster_file , free_cluster , cluster_to_allocate );
859#endif
860
861        // update, in the FAT, the value of last cluster allocated by the index
862        // of free cluster.
863        if ( _update_fat( use_irq , last_cluster_file , free_cluster ) )
864        {
865            _printf("\n[FAT ERROR] in _fat_allocate() : update fat failed\n");
866            return -1;
867        }
868
869        cluster_to_allocate = cluster_to_allocate - 1;
870        // Last cluster allocated is then free_cluster
871        last_cluster_file = free_cluster;
872
873        // Last cluster to allocate done, then we must close the chain of clusters
874        if ( cluster_to_allocate == 0 )
875        {
876            // update, in the FAT, the value of the last cluster allocated by
877            // END_OF_CHAIN_CLUSTER
878            if ( _update_fat( use_irq , last_cluster_file , END_OF_CHAIN_CLUSTER ) )
879            {
880                _printf("\n[FAT ERROR] in _fat_allocate() : update fat failed\n");
881                return -1;
882            }
883        }
884
885        free_cluster = free_cluster + 1;
886
887        // Check if free_cluster is really free (must be true)
888        if ( _get_next_cluster( use_irq , free_cluster ) != FREE_CLUSTER)
889        {
890            _printf("\n[FAT ERROR] in _fat_allocate() : free_cluster not free\n");
891            return -1;
892        }
893    }
894
895    // Update field number_free_cluster and last_cluster_allocated
896    // of structure fat for next fat_allocate
897    _fat.last_cluster_allocated = last_cluster_file;
898    _fat.number_free_cluster    = _fat.number_free_cluster - count;
899
900    if ( _update_fs_info( use_irq ) )
901    {
902        _printf("\n[FAT ERROR] in _fat_allocate() : update fs_info failed\n");
903        return -1;
904    }
905
906    return 0;
907}  // end _fat_allocate()
908
909//////////////////////////////////////////////////////////////////////////////////
910// This function read the blocks defined by the cluster index argument, in a data
911// region containing a directory to search the name of a file/firectory.
912// It returns the cluster index of the file/directory when the name has been found,
913// as well as the file size, and the lba.
914// We consider 3 types of directory entries:
915// - SFN : directory entry associated to a Short File Name (8.3)
916// - LFN : directory entry associated to a Long File Name
917// - XTN : directory entry containing only a name extension for a Long File Name
918// The cluster index is always stored in a SFN or LFN entry.
919// Return cluster index if name found / Return -1 if not found.
920//////////////////////////////////////////////////////////////////////////////////
921static 
922int _scan_directory( unsigned int   use_irq,         // use descheduling mode
923                     unsigned int   cluster,         // cluster of dir_entry
924                     char*          file_name,       // searched file/dir name
925                     unsigned int*  file_size,       // file size
926                     unsigned int*  lba_dir_entry )  // lba of dir_entry
927{
928    char dir_entry[32];   // buffer to store a full directory_entry
929    char name_entry[14];  // buffer to store a 13 characters (partial) name
930
931    char sfn_string[12]    = {[0 ... 10] = ' ', '\0'};  // buffer Short File Name
932    unsigned int  is_sfn   = is_short(file_name, sfn_string); // file_name is short
933    unsigned int  offset   = 0;                         // byte offset in block
934    unsigned int  block_id = _fat.sectors_per_cluster;   // sector index
935    unsigned int  lba      = cluster_to_lba(cluster);   // lba of cluster
936    unsigned int  attr     = 0;                         // dir entry attribute
937    unsigned int  ord      = 0;                         // dir entry sequence
938    unsigned int  found    = 0;                         // searched name found
939    unsigned int  long_name_found = 0;                  // matching XTN found
940    unsigned int  searched_cluster;                     // searched cluster index
941
942#if GIET_DEBUG_FAT
943unsigned int procid  = _get_procid();
944unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
945unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
946unsigned int p       = procid & ((1<<P_WIDTH)-1);
947
948_printf("\n[DEBUG FAT] _scan_directory() : P[%d,%d,%d] enters for %s\n",
949      x, y, p, file_name );
950#endif
951
952    unsigned int  i;
953    for( i = 0 ; i < 32 ; i++ ) dir_entry[i]  = 0;
954    for( i = 0 ; i < 14 ; i++ ) name_entry[i] = 0;
955
956    // load first sector from DATA region into FAT cache
957    // other sectors will be loaded inside loop as required
958    if( _fat_ioc_access( use_irq,
959                         1,               // read
960                         lba,
961                         (unsigned int)_fat.fat_cache,
962                         1 ) )            // one sector
963    {
964        _printf("[\nFAT ERROR] in _scan_directory() : cannot read sector %x\n",
965                lba );
966        return -1;
967    }
968    _fat.cache_lba = lba;
969
970#if ( GIET_DEBUG_FAT > 1 )
971_display_fat_cache();
972#endif
973
974    // in this loop we scan all names in the directory identified by cluster index
975    // - the offset increment is an integer number of directory entry (32 bytes)
976    // - the exit condition is success (name found) or failure (end of directory)
977    while( found == 0 )
978    {
979        // load a new sector if required
980        if (offset >= 512)             
981        {
982            if ( block_id )           // not a new cluster
983            {
984                lba += 1;
985                block_id --;
986            }
987            else                                          // get next cluster
988            {
989                cluster = _get_next_cluster( use_irq , cluster );
990
991                if ( cluster >= END_OF_CHAIN_CLUSTER  ) return END_OF_CHAIN_CLUSTER;
992
993                lba      = cluster_to_lba(cluster);
994                block_id = _fat.sectors_per_cluster;
995            }
996            if( _fat_ioc_access( use_irq,
997                                 1,               // read
998                                 lba, 
999                                 (unsigned int)_fat.fat_cache,
1000                                 1 ) )            // one sector
1001            {
1002                _printf("\n[FAT ERROR] in _scan_directory() : cannot read sector %x\n",
1003                        lba);
1004                return -1;
1005            }
1006            _fat.cache_lba = lba;
1007            block_id--;
1008            offset = offset % 512;
1009        }
1010
1011        // store the directory entry pointed by offset in dir_entry buffer,
1012        // if it a possible candidate for the searched name
1013
1014        attr = _read_entry( DIR_ATTR, _fat.fat_cache + offset, 0);   
1015        ord  = _read_entry( LDIR_ORD, _fat.fat_cache + offset, 0);
1016
1017        if ( is_sfn == 1 )                                // searched name is short
1018        {
1019            if      ( (ord != FREE_ENTRY ) &&
1020                      (ord != NO_MORE_ENTRY) &&
1021                      (attr == ATTR_LONG_NAME_MASK) )    // EXT entry : skipped
1022            {
1023                offset     = offset + ((ord & 0xF) * DIR_ENTRY_SIZE);
1024            }
1025            else if ( (attr != ATTR_LONG_NAME_MASK) && 
1026                      (ord  != FREE_ENTRY) && 
1027                      (ord  != NO_MORE_ENTRY ) )         // SFN entry : to be checked
1028            {
1029                memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );   
1030
1031                get_name_from_short( dir_entry, name_entry );
1032
1033                if ( _strncmp( (char*)sfn_string, 
1034                               (char*)name_entry, 13 ) == 0 )  // short name found
1035                {
1036                    found = 1;
1037                }
1038                else
1039                {
1040                    offset = offset + DIR_ENTRY_SIZE;
1041                }
1042            }
1043            else if (ord == NO_MORE_ENTRY )              // end of directory : return
1044            {
1045                return END_OF_CHAIN_CLUSTER;
1046            }
1047        }
1048        else                                      // searched name is long
1049        {
1050            if( (attr == ATTR_LONG_NAME_MASK) && 
1051                (ord != FREE_ENTRY) &&
1052                (ord != NO_MORE_ENTRY) )                 // EXT entry : to be checked
1053            {
1054                memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );
1055
1056                get_name_from_long( dir_entry, name_entry );
1057
1058                unsigned shift = ((ord & 0xf) - 1) * 13;
1059                if ( _strncmp( (char*)(file_name + shift), 
1060                               (char*)name_entry, 13 ) == 0 )  // matching EXT
1061                {
1062                    if( (ord & 0xf) == 1 )                    // long name found
1063                    {
1064                        long_name_found = 1;
1065                    }
1066                }
1067                offset = offset + DIR_ENTRY_SIZE;
1068            }
1069            else if( (attr != ATTR_LONG_NAME_MASK) && 
1070                     (ord  != FREE_ENTRY) && 
1071                     (ord  != NO_MORE_ENTRY) )
1072            {
1073                if ( long_name_found )                   // LFN entry
1074                {
1075                    memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );
1076                    found = 1;
1077                }
1078                else                                     // SFN entry: must be skipped
1079                {
1080                    offset = offset + DIR_ENTRY_SIZE;
1081                }
1082            }
1083            else if (ord == NO_MORE_ENTRY )                              // end of directory : return
1084            {
1085                return END_OF_CHAIN_CLUSTER;
1086            }
1087        }
1088    }  // end while
1089
1090    // returns cluster index
1091    *file_size       = _read_entry( DIR_FILE_SIZE, dir_entry, 1 );
1092    *lba_dir_entry   = lba;
1093    searched_cluster = (_read_entry( DIR_FST_CLUS_HI, dir_entry, 1 ) << 16) |
1094                       (_read_entry( DIR_FST_CLUS_LO, dir_entry, 1 )      ) ;
1095
1096#if GIET_DEBUG_FAT
1097_printf("\n[DEBUG FAT] _scan_directory() : P[%d,%d,%d] found %s"
1098        " : cluster = %x\n", x, y, p, file_name, searched_cluster );
1099#endif
1100
1101    return searched_cluster;
1102} // end _scan_directory()
1103
1104
1105//////////////////////////////////////////////////////////////////////
1106// This function create a new entry in a directory identified
1107// by "dir_cluster". The name is defined by "name".
1108// The type (dir/file) is defined by "is_file".
1109// Returns cluster index if success, Returns -1 if error.
1110//////////////////////////////////////////////////////////////////////
1111static int _fat_create( char*           name,
1112                        unsigned int    is_file,
1113                        unsigned int    dir_cluster )
1114{
1115    _printf("\n[FAT ERROR] _fat_create() not implemented\n");
1116    return 0;
1117}  //end _fat_create()
1118
1119
1120
1121////////////// Extern functions //////////////////////////////////////////
1122
1123//////////////////////////////////////////////////////////////////////////
1124// This function initializes the FAT structure, including the open
1125// files descriptors array and the lock protecting the FAT,
1126// from informations found in the boot record.
1127// This should be done only once.
1128//////////////////////////////////////////////////////////////////////////
1129// Return 0 if success, exit if failure
1130//////////////////////////////////////////////////////////////////////////
1131int _fat_init( unsigned int use_irq ) 
1132{
1133
1134#if GIET_DEBUG_FAT
1135unsigned int procid  = _get_procid();
1136unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
1137unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1138unsigned int p       = procid & ((1<<P_WIDTH)-1);
1139_printf("\n[DEBUG FAT] P[%d,%d,%d] enters _fat_init\n",x,y,p);
1140#endif
1141
1142    // FAT initialisation should be done only once
1143    if ( _fat.initialised == FAT_INITIALISED )
1144    {
1145        _printf("\n[FAT ERROR] Strange, FAT already initialised...\n");
1146        _exit();
1147    }
1148
1149    // load Boot Record (VBR) into fat cache
1150    if ( _fat_ioc_access( use_irq,
1151                          1,                   // read
1152                          0,                   // sector index
1153                          (unsigned int)_fat.fat_cache,
1154                          1 ) )                // one sector
1155    {
1156        _printf("\n[FAT ERROR] in _fat_init() cannot load VBR\n");
1157        _exit();
1158    }
1159    _fat.cache_lba = 0;
1160
1161#if GIET_DEBUG_FAT > 1
1162_printf("\n[DEBUG FAT] _fat_init() : Boot Sector Loaded\n");
1163_display_fat_cache();
1164#endif
1165
1166    // checking various FAT32 assuptions from boot sector
1167    if( _read_entry( BPB_BYTSPERSEC, _fat.fat_cache, 1 ) != 512 )
1168    {
1169        _printf("\n[FAT ERROR] The sector size must be 512 bytes\n");
1170        _exit();
1171    }
1172    if( _read_entry( BPB_NUMFATS, _fat.fat_cache, 1 ) != 1 )
1173    {
1174        _printf("\n[FAT ERROR] The number of FAT copies in FAT region must be 1\n");
1175        _exit();
1176    }
1177    if( (_read_entry( BPB_FAT32_FATSZ32, _fat.fat_cache, 1 ) & 0xF) != 0 )
1178    {
1179        _printf("\n[FAT ERROR] The FAT region must be multiple of 32 sectors\n");
1180        _exit();
1181    }
1182    if( _read_entry( BPB_FAT32_ROOTCLUS, _fat.fat_cache, 1 ) != 2 )
1183    {
1184        _printf("\n[FAT ERROR] The first cluster index must be 2\n");
1185        _exit();
1186    }
1187    // FS Info always in sector 1
1188    _fat.fs_info_lba         = _read_entry( BPB_FAT32_FSINFO, _fat.fat_cache, 1 );
1189
1190    // initialise fat descriptor from VBR
1191    _fat.sectors_per_cluster = _read_entry( BPB_SECPERCLUS, _fat.fat_cache, 1 );
1192    _fat.sector_size         = _read_entry( BPB_BYTSPERSEC, _fat.fat_cache, 1 );
1193    _fat.cluster_size        = _fat.sectors_per_cluster * 512;
1194    _fat.fat_sectors         = _read_entry( BPB_FAT32_FATSZ32, _fat.fat_cache, 1 );
1195    _fat.fat_lba             = _read_entry( BPB_RSVDSECCNT, _fat.fat_cache, 1 );
1196    _fat.data_lba            = _fat.fat_lba + _fat.fat_sectors;
1197    _fat.initialised         = FAT_INITIALISED;
1198
1199    // initalise the lock protecting the FAT
1200    _spin_lock_init( &_fat.fat_lock );
1201
1202    // initialise file descriptor array
1203    unsigned int   n;
1204    for( n = 0 ; n < GIET_OPEN_FILES_MAX ; n++ ) _fat.fd[n].used = 0;
1205
1206#if GIET_DEBUG_FAT
1207_printf("\n[DEBUG FAT] _fat_init() : FS_INFO Sector = %x\n", _fat.fs_info_lba );
1208#endif
1209
1210    // load FS_INFO into fat cache
1211    if ( _fat_ioc_access( use_irq,
1212                          1,                  // read
1213                          _fat.fs_info_lba,   
1214                          (unsigned int)_fat.fat_cache,
1215                          1 ) )               // one sector
1216    { 
1217        _printf("\n[FAT ERROR] in _fat_init() cannot load FS_INFO Sector\n"); 
1218        _exit();
1219    }
1220    _fat.cache_lba = _fat.fs_info_lba;
1221
1222    _fat.number_free_cluster    = _read_entry( FS_FREE_CLUSTER     , _fat.fat_cache, 1);
1223    _fat.last_cluster_allocated = _read_entry( FS_FREE_CLUSTER_HINT, _fat.fat_cache, 1);
1224
1225#if GIET_DEBUG_FAT
1226_fat_print();
1227_printf("\n[DEBUG FAT] P[%d,%d,%d] exit _fat_init()\n", x,y,p );
1228#endif
1229
1230    return 0;
1231}  // end _fat_init()
1232
1233///////////////////////////////////////////////////////////////////////////////
1234// This function checks that the kernel FAT structure has been initialised.
1235// It searches a file identified by the "pathname" argument.
1236// It starts from root (cluster 2) to scan successively each subdirectory.
1237// When the file is not found, but the path is found, and "creat" is set,
1238// a new file is created and introduced in the directory.
1239// Finally, it sets a new open file in the file descriptors array.
1240// The same file can be open several times by differents tasks.
1241///////////////////////////////////////////////////////////////////////////////
1242// Returns file descriptor index if success, returns -1 if error.
1243///////////////////////////////////////////////////////////////////////////////
1244int _fat_open( unsigned int use_irq,       // use descheduling mode if possible
1245               char*        pathname,
1246               unsigned int creat )
1247{
1248    char                 name[256];        // buffer for one name in pathname
1249    unsigned int         nb_read;              // number of characters written in name[]
1250    unsigned int         cluster;          // current cluster index when scanning FAT
1251    unsigned int         dir_cluster;      // previous cluster index when scanning FAT
1252    unsigned int         fd_id;            // index when scanning file descriptors array
1253    unsigned int         file_size = 0;    // number of bytes
1254    unsigned int         last_name = 0;    // directory containing file name is reached
1255    unsigned int         lba       = 0;    // lba of dir_entry for this file
1256   
1257#if GIET_DEBUG_FAT
1258unsigned int procid  = _get_procid();
1259unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
1260unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1261unsigned int p       = procid & ((1<<P_WIDTH)-1);
1262_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] enters for path %s\n",
1263        x, y, p, pathname );
1264#endif
1265
1266    // checking creat argument
1267    if ( creat )
1268    {
1269        _printf("\n[FAT ERROR] in _fat_open() : create not supported yet\n");
1270        return -1;
1271    }
1272
1273    // checking FAT initialised
1274    if( _fat.initialised != FAT_INITIALISED )
1275    {
1276        _printf("\n[FAT ERROR] in _fat_open() : FAT not initialised\n");
1277        return -1;
1278    }
1279    // takes the FAT lock for exclusive access
1280    _spin_lock_acquire( &_fat.fat_lock );
1281
1282#if GIET_DEBUG_FAT
1283_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] takes the FAT lock\n",
1284        x, y, p );
1285#endif
1286 
1287    // Scan the directories, starting from the root directory (cluster 2)
1288    // - The get_name_from_path() function extracts (successively)
1289    //   each directory name from the pathname, and store it in name[] buffer
1290    // - The _scan_directory() function scan one (or several) cluster(s) containing
1291    //   a directory looking for name[], and return the cluster index
1292    //   corresponding to the directory/file found.
1293    nb_read     = 0;
1294    cluster     = 2;
1295    last_name   = 0;
1296    while ( get_name_from_path( pathname, name, &nb_read) )
1297    {
1298
1299#if GIET_DEBUG_FAT
1300_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] search file/dir %s\n",
1301        x, y, p, name );
1302#endif
1303
1304        // test if we reach the last name (file name)
1305        if( pathname[nb_read] == 0 ) 
1306        {
1307            last_name   = 1;
1308            dir_cluster = cluster;
1309        }
1310
1311        // scan current directory
1312        cluster = _scan_directory( use_irq , cluster , name , &file_size , &lba );
1313
1314        if( cluster == END_OF_CHAIN_CLUSTER && last_name && creat )
1315        {
1316            cluster = _fat_create( name, 1, dir_cluster );
1317        }
1318        else if ( cluster == END_OF_CHAIN_CLUSTER )
1319        {
1320            _printf("\n[FAT ERROR] in _fat_open() cannot found %s\n", name );
1321            _spin_lock_release( &_fat.fat_lock );
1322            return -1;
1323        }
1324    }
1325
1326#if GIET_DEBUG_FAT
1327_printf("\n[DEBUG FAT] P[%d,%d,%d] in _fat_open() : cluster for %s = %x\n",
1328       x, y, p, pathname, cluster );
1329#endif
1330
1331    // check the next value for cluster index found
1332    unsigned next = _get_next_cluster( use_irq , cluster );
1333
1334    if ( (next != BAD_CLUSTER) && (next != FREE_CLUSTER) )
1335    {
1336        // Search an empty slot scanning open file descriptors array
1337        fd_id = 0;
1338        while ( _fat.fd[fd_id].used != 0 && fd_id < GIET_OPEN_FILES_MAX )
1339        {
1340            fd_id++;
1341        }
1342
1343        // set file descriptor if found empty slot
1344        if ( fd_id < GIET_OPEN_FILES_MAX )
1345        {
1346            _fat.fd[fd_id].used          = 1;
1347            _fat.fd[fd_id].first_cluster = cluster;
1348            _fat.fd[fd_id].file_size     = file_size;
1349            _fat.fd[fd_id].lba_dir_entry = lba;
1350            _strcpy( _fat.fd[fd_id].name, pathname );
1351
1352#if GIET_DEBUG_FAT
1353_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] exit : fd = %d for file %s\n",
1354        x, y, p, fd_id, pathname );
1355#endif
1356
1357            // release FAT lock
1358            _spin_lock_release( &_fat.fat_lock );
1359
1360            return fd_id;
1361        }
1362        else
1363        {
1364            _printf("\n[FAT ERROR] in _fat_open() for file %s : fd array full\n", 
1365                    pathname );
1366            _spin_lock_release( &_fat.fat_lock );
1367            return -1;
1368        }
1369    }
1370    else
1371    {
1372        _printf("\n[FAT ERROR] in _fat_open() for file %s : bad cluster\n",
1373                pathname );
1374        _spin_lock_release( &_fat.fat_lock );
1375        return -1;
1376    }
1377} // end _fat_open()
1378
1379///////////////////////////////////////////////////////////////////////////////
1380// For an open file, identified by the file descriptor index, transfer
1381// an integer number of sectors from block device to a memory buffer.
1382// If the number of requested sectors exceeds the file size, it is reduced.
1383///////////////////////////////////////////////////////////////////////////////
1384// Returns number of sectors transfered if success, < 0 if error.
1385///////////////////////////////////////////////////////////////////////////////
1386int _fat_read( unsigned int use_irq,    // use descheduling mode if possible
1387               unsigned int fd_id,      // file descriptor
1388               void*        buffer,     // target buffer base address
1389               unsigned int count,      // number of sector to read
1390               unsigned int offset )    // nuber of sectors to skip in file
1391{
1392    unsigned int spc = _fat.sectors_per_cluster;
1393
1394    unsigned int file_size;         // number of bytes in file
1395    unsigned int file_sectors;      // number of sectors in file
1396    unsigned int total_sectors;     // actual number of sectors to be transfered
1397    unsigned int cluster;           // cluster index
1398    unsigned int clusters_to_skip;  // number of clusters to skip because offset
1399    unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
1400
1401    // arguments checking
1402    if ( fd_id >= GIET_OPEN_FILES_MAX )
1403    { 
1404        _printf("\n[FAT ERROR] in _fat_read() : illegal file descriptor index\n");
1405        return -1;
1406    }
1407    if ( _fat.fd[fd_id].used != 1 )
1408    {
1409        _printf("\n[FAT ERROR] in _fat_read() : file not open\n");
1410        return -1;
1411    }
1412    if ( ((unsigned int)buffer & 0x1FF) != 0 )
1413    {
1414        _printf("\n[FAT ERROR] in _fat_read() : memory buffer not sector aligned\n");
1415        return -1;
1416    }
1417
1418    // compute file size as a number of sectors
1419    file_size    = _fat.fd[fd_id].file_size;
1420    if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1421    else                     file_sectors = (file_size >> 9); 
1422
1423    if ( offset >= file_sectors )
1424    {
1425        _printf("\n[FAT ERROR] offset larger than number of sectors\n");
1426        return -1;
1427    }
1428
1429    // compute total number of sectors to read
1430    if ( file_sectors < (offset + count) ) total_sectors = file_sectors - offset;
1431    else                                   total_sectors = count;
1432
1433    // compute clusters and sectors to be skipped
1434    clusters_to_skip = offset / spc;
1435    sectors_to_skip  = offset % spc;
1436   
1437    // get first cluster index
1438    cluster = _fat.fd[fd_id].first_cluster;
1439
1440#if GIET_DEBUG_FAT
1441unsigned int procid  = _get_procid();
1442unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
1443unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1444unsigned int p       = procid & ((1<<P_WIDTH)-1);
1445_printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] enters for file %s\n"
1446        " - buffer vbase     = %x\n"
1447        " - skipped sectors  = %x\n"
1448        " - read sectors     = %x\n"
1449        " - first cluster    = %x\n"
1450        " - skipped clusters = %x\n",
1451        x, y, p, _fat.fd[fd_id].name, (unsigned int)buffer,
1452        offset, count, cluster, clusters_to_skip );
1453#endif
1454
1455    // compute index of first cluster to be loaded
1456    while ( clusters_to_skip )
1457    {
1458        cluster = _get_next_cluster( use_irq , cluster );
1459        clusters_to_skip--;
1460    }
1461
1462    // variables used in the loop on clusters
1463    int             todo_sectors;   // number of sectors still to be loaded
1464    unsigned int    lba;            // first sector index on device
1465    unsigned int    iter_sectors;   // number of sectors to load in iteration
1466    unsigned int    dst;            // pointer on target buffer
1467
1468    // initialize these variables for the first iteration
1469    todo_sectors  = total_sectors;
1470    dst           = (unsigned int)buffer;
1471    lba           = cluster_to_lba(cluster) + sectors_to_skip;
1472    if( total_sectors < (spc - sectors_to_skip) ) iter_sectors = total_sectors;
1473    else                                          iter_sectors = spc - sectors_to_skip; 
1474
1475    // loop on the clusters: one IOC access per cluster
1476    while ( todo_sectors > 0 )
1477    {
1478
1479#if GIET_DEBUG_FAT
1480_printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] makes an IOC read\n"
1481        "  cluster = %x / buffer = %x / lba = %x / sectors = %d\n",
1482        x, y, p, cluster, dst, lba, iter_sectors );
1483#endif
1484
1485        if( _fat_ioc_access( use_irq,
1486                             1,                 // read
1487                             lba, 
1488                             dst,               // buffer address
1489                             iter_sectors ) )   // number of sectors
1490        {
1491            _printf("\n[FAT ERROR] in _fat_read() cannot load block %x", lba );
1492            return -1;
1493        }
1494         
1495        // update variables for next iteration
1496        cluster      = _get_next_cluster( use_irq , cluster );
1497        todo_sectors = todo_sectors - iter_sectors;
1498        dst          = dst + (iter_sectors << 9);
1499        lba          = cluster_to_lba(cluster);
1500        if ( todo_sectors > spc ) iter_sectors = spc;
1501        else                      iter_sectors = todo_sectors;
1502    }
1503         
1504    // returns number of sectors actually transfered
1505    return total_sectors;
1506
1507}  // end _fat_read()
1508
1509///////////////////////////////////////////////////////////////////////////////
1510// For an open file, identified by the file descriptor index, transfer
1511// an integer number of sectors from a memory buffer to block device.
1512// Allocate new clusters if the offset+count larger than current file size,
1513// but the offset should be smaller than the current file size...
1514///////////////////////////////////////////////////////////////////////////////
1515// Returns number of sectors written if success, < 0 if error.
1516///////////////////////////////////////////////////////////////////////////////
1517int _fat_write( unsigned int use_irq,    // use descheduling mode if possible
1518                unsigned int fd_id,      // file descriptor
1519                void*        buffer,     // target buffer base address
1520                unsigned int count,      // number of sector to write
1521                unsigned int offset )    // nuber of sectors to skip in file
1522{
1523
1524    unsigned int spc = _fat.sectors_per_cluster;
1525
1526    unsigned int file_size;         // number of bytes in file
1527    unsigned int file_sectors;      // number of sectors in file
1528    unsigned int cluster;           // cluster index
1529    unsigned int clusters_to_skip;  // number of clusters to skip because offset
1530    unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
1531    unsigned int allocate;          // need allocate or not
1532    unsigned int current_cluster;   // number of cluster allocated to the file
1533    unsigned int required_cluster;  // number of cluster needed for the write
1534
1535    // compute file size as a number of sectors
1536    file_size    = _fat.fd[fd_id].file_size;
1537    if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1538    else                     file_sectors = (file_size >> 9); 
1539
1540    // Compute the number of clusters occupied by the file
1541    current_cluster = file_sectors / spc;
1542
1543    // Compute the number of clusters that will occupy the file (after fat_write)
1544    required_cluster = (count + offset) / spc;
1545
1546    // Check if we need to allocate new cluster(s) for the file 
1547    allocate = ( required_cluster > current_cluster );
1548
1549#if GIET_DEBUG_FAT
1550unsigned int procid  = _get_procid();
1551unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
1552unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1553unsigned int p       = procid & ((1<<P_WIDTH)-1);
1554
1555_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] enters for file %s\n"
1556        " - buffer vbase    = %x\n"
1557        " - skipped sectors = %x\n"
1558        " - write sectors   = %x\n"
1559        " - file sectors    = %x\n"
1560        " - need_allocate   = %d\n",
1561        x, y, p, _fat.fd[fd_id].name, (unsigned int)buffer,
1562        offset, count, file_sectors, allocate );
1563#endif
1564
1565    // arguments checking
1566    if ( fd_id >= GIET_OPEN_FILES_MAX )
1567    { 
1568        _printf("\n[FAT ERROR] in _fat_write() : illegal file descriptor index\n");
1569        return -1;
1570    }
1571    if ( _fat.fd[fd_id].used != 1 )
1572    {
1573        _printf("\n[FAT ERROR] in _fat_write() : file not open\n");
1574        return -1;
1575    }
1576    if ( ((unsigned int)buffer & 0x1FF) != 0 )
1577    {
1578        _printf("\n[FAT ERROR] in _fat_write() : memory buffer not sector aligned\n");
1579        return -1;
1580    }
1581
1582    if ( allocate  )
1583    {
1584        if ( _fat_allocate( use_irq , fd_id, (required_cluster-current_cluster) ) )
1585        {
1586            _printf("\n[FAT ERROR] in _fat_write() : fat_allocate failed\n");
1587            return -1;
1588        }
1589    }
1590
1591    // compute clusters and sectors to be skipped
1592    clusters_to_skip = offset / spc;
1593    sectors_to_skip  = offset % spc;
1594   
1595    // get first cluster index
1596    cluster = _fat.fd[fd_id].first_cluster;
1597
1598#if GIET_DEBUG_FAT
1599_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] get cluster %x\n",
1600        x, y, p, cluster );
1601#endif
1602
1603    // compute index of first cluster to be loaded
1604    while ( clusters_to_skip )
1605    {
1606        cluster = _get_next_cluster( use_irq , cluster );
1607        clusters_to_skip--;
1608    }
1609
1610    // variables used in the loop on clusters
1611    int             todo_sectors;   // number of sectors still to be loaded
1612    unsigned int    lba;            // first sector index on device
1613    unsigned int    iter_sectors;   // number of sectors to load in iteration
1614    unsigned int    src;            // pointer on target buffer
1615
1616    // initialize these variables for the first iteration
1617    todo_sectors  = count;
1618    src           = (unsigned int)buffer;
1619    lba           = cluster_to_lba(cluster) + sectors_to_skip;
1620    if( count < (spc - sectors_to_skip) ) iter_sectors = count;
1621    else                                  iter_sectors = spc - sectors_to_skip; 
1622
1623    // loop on the clusters
1624    while ( todo_sectors > 0 )
1625    {
1626
1627#if GIET_DEBUG_FAT
1628_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] makes an IOC write"
1629        "  cluster = %x / buffer = %x / lba = %x / sectors = %d\n",
1630        x, y, p, cluster, src, lba, iter_sectors );
1631#endif
1632
1633        if( _fat_ioc_access( use_irq,
1634                             0,                 // write
1635                             lba, 
1636                             src,               // source buffer address
1637                             iter_sectors ) )   // number of sectors
1638        {
1639            _printf("\n[FAT ERROR] in _fat_write() cannot write block %x\n", lba );
1640            return -1;
1641        }
1642         
1643        // update variables for next iteration
1644        cluster      = _get_next_cluster( use_irq , cluster );
1645        todo_sectors = todo_sectors - iter_sectors;
1646        src          = src + (iter_sectors << 9);
1647        lba          = cluster_to_lba(cluster);
1648        if ( todo_sectors > spc ) iter_sectors = spc;
1649        else                      iter_sectors = todo_sectors;
1650    }
1651
1652    // Update structure file descriptor, field file_size with
1653    // the new file size if the file is bigger than the previous file
1654    if ( ( offset + count ) > file_sectors )
1655    {
1656        _fat.fd[fd_id].file_size = (count + offset) << 9;
1657    }
1658
1659    // Update entry of directory with the new value
1660    // of file size (Field : DIR_FILE_SIZE)
1661    if ( _update_entry( use_irq, fd_id , DIR_FILE_SIZE , _fat.fd[fd_id].file_size ) )
1662    {
1663        _printf("\n[FAT ERROR] in _fat_write() update entry failed\n");
1664        return -1;
1665    }
1666         
1667    // returns number of sectors actually transfered
1668    return count;
1669}  // end _fat_write()
1670
1671/////////////////////////////////////////////////////////////////////////////////
1672// Return stats of a file identified by "fd".
1673// (Only the file_size in sectors for this moment)
1674/////////////////////////////////////////////////////////////////////////////////
1675// Returns file size (on sectors) on success, -1 on failure.
1676/////////////////////////////////////////////////////////////////////////////////
1677int _fat_fstat( unsigned int fd_id )
1678{
1679    unsigned int file_size    = 0;
1680    unsigned int file_sectors = 0;
1681
1682    if( (fd_id < GIET_OPEN_FILES_MAX) )
1683    {
1684        file_size = _fat.fd[fd_id].file_size;
1685
1686        if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1687        else                     file_sectors = (file_size >> 9); 
1688
1689        return file_sectors;
1690    }
1691    else
1692    {
1693        _printf("\n[FAT ERROR] in _fat_fstat() : illegal file descriptor index\n");
1694        return -1;
1695    } 
1696} // end _fat_fstat()
1697
1698/////////////////////////////////////////////////////////////////////////////////
1699// Close the file identified by the file_descriptor index.
1700/////////////////////////////////////////////////////////////////////////////////
1701// Returns 0 on success, -1 on failure.
1702/////////////////////////////////////////////////////////////////////////////////
1703int _fat_close( unsigned int fd_id )
1704{
1705    if( (fd_id < GIET_OPEN_FILES_MAX) )
1706    {
1707        _fat.fd[fd_id].used = 0;
1708        return 0;
1709    }
1710    else
1711    {
1712        _printf("\n[FAT ERROR] in _fat_close() : illegal file descriptor index\n");
1713        return -1;
1714    } 
1715} // end fat_close()
1716
1717/////////////////////////////////////////////////////////////////////////////////
1718// The following function implement the user_level system call.
1719// The flags argument is not used, as file access modes are not implemented yet.
1720/////////////////////////////////////////////////////////////////////////////////
1721// Return the file descriptor index if success / return -1 if failure
1722/////////////////////////////////////////////////////////////////////////////////
1723int _fat_user_open( char*  pathname,         // absolute pathname from root
1724                    unsigned int flags )     // unused: TODO
1725{
1726    return _fat_open( 1,        // use descheduling mode if possible
1727                      pathname, 
1728                      0 );      // no creation if not found
1729}
1730
1731/////////////////////////////////////////////////////////////////////////////////
1732// The following function implement the user_level system call.
1733// This function should be modified to respect the UNIX specification.
1734/////////////////////////////////////////////////////////////////////////////////
1735// Return number of sectors actually transfered if success / return -1 if failure
1736/////////////////////////////////////////////////////////////////////////////////
1737int _fat_user_read( unsigned int fd,        // file descriptor index
1738                    void*        buffer,    // destination buffer
1739                    unsigned int count,     // number of sectors to read
1740                    unsigned int offset )   // number of sectors to skip
1741{
1742    return _fat_read( 1,        // use descheduling mode if possible
1743                      fd,
1744                      buffer, 
1745                      count, 
1746                      offset );
1747}
1748
1749/////////////////////////////////////////////////////////////////////////////////
1750// The following function implement the user_level system call.
1751// This function should be modified to respect the UNIX specification.
1752/////////////////////////////////////////////////////////////////////////////////
1753// Return number of sectors actually transfered if success / return -1 if failure
1754/////////////////////////////////////////////////////////////////////////////////
1755int _fat_user_write( unsigned int fd,       // file descriptor
1756                     void*        buffer,   // source buffer
1757                     unsigned int count,    // number of sectors to write
1758                     unsigned int offset )  // number of sectors to skip on file
1759{
1760    return _fat_write( 1,       // use descheduling mode if possible
1761                       fd,
1762                       buffer, 
1763                       count, 
1764                       offset );
1765}
1766
1767/////////////////////////////////////////////////////////////////////////////////
1768int _fat_user_lseek( unsigned int fd_id,
1769                     unsigned int offset,
1770                     unsigned int whence )
1771{
1772    _printf("\n[GIET ERROR] _fat_user_lseek() not implemented\n");
1773    _exit();
1774    return 0;
1775}
1776
1777
1778// Local Variables:
1779// tab-width: 4
1780// c-basic-offset: 4
1781// c-file-offsets:((innamespace . 0)(inline-open . 0))
1782// indent-tabs-mode: nil
1783// End:
1784// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1785
Note: See TracBrowser for help on using the repository browser.