Ignore:
Timestamp:
Jul 8, 2015, 3:35:36 PM (9 years ago)
Author:
alain
Message:

Major evolution of the FAT32 library: i
Introduce a distributed File-Caches architecture,
a distributed FAT-Cache, and a distributed Inodes-Tree structure.
Provide Posix-like system calls.

Location:
soft/giet_vm/giet_fat32
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_fat32/fat32.c

    r569 r587  
    11//////////////////////////////////////////////////////////////////////////////////
    2 // File     : fat32.c
    3 // Date     : 01/09/2013
    4 // Authors  : Marco Jankovic, Cesar Fuguet & Alain Greiner
     2// Date     : 01/06/2015
     3// Authors  : Alain Greiner
    54// Copyright (c) UPMC-LIP6
    65//////////////////////////////////////////////////////////////////////////////////
    76// The fat32.h and fat32.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.
     7// to a FAT32 disk on a block device. It is intended to be used by both
     8// the boot code and the kernel code.
    109//////////////////////////////////////////////////////////////////////////////////
    1110// Implementation notes:
     
    1312//    the block device. The physical sector size is supposed to be 512 bytes.
    1413// 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 sector.
     14//    8 sectors (4K bytes) and the cluster index is a 32 bits word.
     15// 3. Each file or directory referenced by the software is represented
     16//    by an "inode". The set of "inodes" is organised as a tree, that is
     17//    a sub-tree of the complete file system existing on the block device.
     18// 4. A given file can be referenced by several software tasks, and each task
     19//    will use a private handler, called a "file descriptor", allocated by the OS
     20//    when the task open the file, that is organised as an indexed array.
     21// 5. This FAT32 library implements (N+1) caches : one private "File_ Cache"
     22//    for each referenced file or directory, and a specific "Fat_Cache" for
     23//    the FAT itself. Each cache contain a variable number of clusters that are
     24//    dynamically allocated when they are accessed, and organised as a 64-Tree.
     25//////////////////////////////////////////////////////////////////////////////////
     26// General Debug Policy:
     27// The global variable GIET_DEBUG_FAT is defined in the giet_config.h file.
     28// The debug is activated if (proctime > GIET_DEBUG_FAT) && (GIET_DEBUG_FAT != 0)
     29// The GIET_DEBUG_FAT bit 0 defines the level of debug:
     30//    if   (GIET_DEBUG_FAT & 0x1)    => detailed debug
     31//    else                           => external functions only
    1732//////////////////////////////////////////////////////////////////////////////////
    1833
     
    2237#include <utils.h>
    2338#include <vmem.h>
     39#include <kernel_malloc.h>
    2440#include <bdv_driver.h>
    2541#include <hba_driver.h>
     
    3046
    3147//////////////////////////////////////////////////////////////////////////////////
    32 //      Global variable : internal FAT representation
    33 //////////////////////////////////////////////////////////////////////////////////
    34 
    35 extern fat32_fs_t _fat;
    36 
    37 extern unsigned int _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
    38  
     48//               Global variables
     49//////////////////////////////////////////////////////////////////////////////////
     50
     51// Fat-Descriptor
     52__attribute__((section(".kdata")))
     53fat_desc_t _fat __attribute__((aligned(64)));
     54
     55// buffer used by boot code as a simple cache when scanning FAT
     56__attribute__((section(".kdata")))
     57unsigned char  _fat_buffer_fat[4096] __attribute__((aligned(64)));
     58
     59// buffer used by boot code as a simple cache when scanning a directory in DATA region
     60__attribute__((section(".kdata")))
     61unsigned char  _fat_buffer_data[4096] __attribute__((aligned(64)));
     62
     63// lba of cluster in fat_buffer_fat
     64__attribute__((section(".kdata")))
     65unsigned int   _fat_buffer_fat_lba;
     66
     67// lba of cluster in fat_buffer_data
     68__attribute__((section(".kdata")))
     69unsigned int   _fat_buffer_data_lba;
     70
     71//////////////////////////////////////////////////////////////////////////////////
     72//////////////////////////////////////////////////////////////////////////////////
     73//                  Static functions declaration
     74//////////////////////////////////////////////////////////////////////////////////
     75//////////////////////////////////////////////////////////////////////////////////
     76
     77
     78///////////////////////////////////////////////////////////////////////////////////
     79// This debug function displays the content of a 512 bytes buffer "buf",
     80// with an identifier defined by the "string" and "block_id" arguments.
     81///////////////////////////////////////////////////////////////////////////////////
     82
     83#if GIET_DEBUG_FAT
     84static void _display_one_block( unsigned char* buf,
     85                                char*          string,
     86                                unsigned int   block_id );
     87#endif
     88
     89//////////////////////////////////////////////////////////////////////////////////
     90// This debug function displays the FAT descriptor.
     91//////////////////////////////////////////////////////////////////////////////////
     92
     93#if GIET_DEBUG_FAT
     94static void _display_fat_descriptor();
     95#endif
     96
    3997/////////////////////////////////////////////////////////////////////////////////
    40 // This function computes the memory buffer physical address, and calls
    41 // the proper IOC driver depending on the subtype (BDV / HBA / SDC / SPI / RDK).
    42 // The use_irq argument allows to activate the descheduling mode, if it
    43 // supported by the IOC driver subtype
     98// This debug function displays the sequence of clusters allocated to a
     99// file (or directory) identified by the "inode" argument.
    44100/////////////////////////////////////////////////////////////////////////////////
    45 // Return 0 in case of success, return -1 in case of error
     101
     102#if GIET_DEBUG_FAT
     103static void _display_clusters_list( fat_inode_t* inode );
     104#endif
     105
    46106/////////////////////////////////////////////////////////////////////////////////
    47 static
    48 int _fat_ioc_access( unsigned int use_irq,
    49                      unsigned int to_mem,
    50                      unsigned int lba,
    51                      unsigned int buf_vaddr,
    52                      unsigned int count )
     107// The following function transfers one or several blocks between the device
     108// and a memory buffer identified by a virtual address.
     109// It computes the memory buffer physical address, and calls the proper
     110// IOC driver depending on the subtype (BDV / HBA / SDC / SPI / RDK).
     111// The use_irq argument allows to activate the descheduling mode,
     112// if it supported by the IOC driver subtype
     113// It returns O  in case of success.
     114// It returns -1 in case of error.
     115/////////////////////////////////////////////////////////////////////////////////
     116
     117static int _fat_ioc_access( unsigned int use_irq,
     118                            unsigned int to_mem,
     119                            unsigned int lba,
     120                            unsigned int buf_vaddr,
     121                            unsigned int count );
     122
     123//////////////////////////////////////////////////////////////////////////////////
     124// The following function returns in the "desc" argument a pointer on a buffer
     125// descriptor contained in a File_Cache, or in the Fat_Cache.
     126// The searched buffer is idenfified by the "inode" and "cluster_id" arguments.
     127// If the "inode" pointer is not NULL, the searched cache is a File-Cache.
     128// If the "inode" pointer is NULL, the searched cache is the Fat-Cache,
     129// The "cluster_id" argument is the buffer index in the file (or in the FAT).
     130// In case of miss, it allocate a 4 Kbytes buffer and a cluster descriptor
     131// from the local kernel heap, and calls the _fat_ioc_access() function to load
     132// the missing cluster from the block device.
     133// It returns O  in case of success.
     134// It returns 1 in case of error.
     135//////////////////////////////////////////////////////////////////////////////////
     136
     137static unsigned int _get_buffer_from_cache( fat_inode_t*        inode,
     138                                            unsigned int        cluster_id,
     139                                            fat_cache_desc_t**  desc );
     140
     141////////////////////////////////////////////////////////////////////////////////
     142// This function extract a (partial) name from a LFN directory entry.
     143////////////////////////////////////////////////////////////////////////////////
     144
     145static void _get_name_from_long( unsigned char* buffer,
     146                                 char*          name );
     147
     148////////////////////////////////////////////////////////////////////////////////
     149// The following function extract a name from a NORMAL directory entry.
     150////////////////////////////////////////////////////////////////////////////////
     151
     152static void _get_name_from_short( unsigned char* buffer,
     153                                  char*          name );
     154
     155//////////////////////////////////////////////////////////////////////////////////
     156// This function returns the number of levels of a File-Cache (or Fat-Cache)
     157// from the size of the file (or FAT).
     158//////////////////////////////////////////////////////////////////////////////////
     159
     160static inline unsigned int _get_levels_from_size( unsigned int size );
     161
     162///////////////////////////////////////////////////////////////////////////////////
     163// The following function analyses the "pathname" argument, from the character
     164// defined by the "nb_read" argument.
     165// It copies the found name in the "name" buffer (without '/'),
     166// and updates the "nb_read" argument.
     167// It returns 0 if success.
     168// It returns 1 if one name length > NAME_MAX_SIZE characters
     169///////////////////////////////////////////////////////////////////////////////////
     170
     171static unsigned int _get_name_from_path( char*          pathname,
     172                                         char*          name,
     173                                         unsigned int*  nb_read );
     174
     175////////////////////////////////////////////////////////////////////////////////
     176// The following function scan the "pathname" argument, and copies in the
     177// "name" buffer the last name in path (leaf name).
     178// It returns 0 if success.
     179// It returns 1 if one name length > NAME_MAX_SIZE characters
     180////////////////////////////////////////////////////////////////////////////////
     181static unsigned int _get_last_name( char*   pathname,
     182                                    char*   name );
     183
     184//////////////////////////////////////////////////////////////////////////////////
     185// The following function access the Fat-Cache and returns in the "value"
     186// argument the content of the FAT slot identified by the "cluster" argument.
     187// It loads the missing cluster from block device into cache in case of miss.
     188// It returns 0 if success.
     189// It returns 1 if error.
     190//////////////////////////////////////////////////////////////////////////////////
     191
     192static unsigned int _get_fat_entry( unsigned int  cluster,
     193                                    unsigned int* value );
     194
     195//////////////////////////////////////////////////////////////////////////////////
     196// The following function writes a new "value" in the Fat-Cache, in the slot
     197// identified by the "cluster" argument. 
     198// It loads the missing cluster from block device into cache in case of miss.
     199// It returns 0 if success,
     200// It returns 1 if error.
     201//////////////////////////////////////////////////////////////////////////////////
     202
     203static unsigned int _set_fat_entry( unsigned int  cluster,
     204                                    unsigned int  value );
     205
     206//////////////////////////////////////////////////////////////////////////////////
     207// The following function introduces the inode identified by the "child" argument,
     208// as a new child of the "parent" inode in the Inode-Tree.
     209// All checking are supposed to be done by the caller.
     210// Nor the File-Cache, neither the block device are modified.
     211//////////////////////////////////////////////////////////////////////////////////
     212
     213static void _add_inode_in_tree( fat_inode_t*  child,
     214                                fat_inode_t*  parent );
     215
     216//////////////////////////////////////////////////////////////////////////////////
     217// The following function removes one inode identified by the "inode" argument
     218// from the Inode-Tree. All checking are supposed to be done by the caller.
     219// Nor the File-Cache, neither the block device are modified.
     220//////////////////////////////////////////////////////////////////////////////////
     221
     222static void _remove_inode_from_tree( fat_inode_t* inode );
     223
     224//////////////////////////////////////////////////////////////////////////////////
     225// This recursive function scan one File-Cache (or Fat-Cache) from root to leaves,
     226// to writes all dirty clusters to block device, and reset the dirty bits.
     227// The cache is identified by the "root" an "levels" arguments.
     228// The "string" argument is only used for debug : inode name or Fat.
     229// It returns 0 if success.
     230// It returns 1 if error.
     231//////////////////////////////////////////////////////////////////////////////////
     232
     233static unsigned int _update_device_from_cache( unsigned int      levels,
     234                                               fat_cache_node_t* root,
     235                                               char*             string );
     236
     237//////////////////////////////////////////////////////////////////////////////////
     238// The following function access directly the FS_INFO block on the block device,
     239// to update the "first_free_cluster" and "free_clusters_number" values,
     240// using only the Fat-Descriptor single block buffer.
     241// It return 0 in case of success.
     242// It return 1 in case of error.
     243//////////////////////////////////////////////////////////////////////////////////
     244
     245static unsigned int _update_fs_info();
     246
     247//////////////////////////////////////////////////////////////////////////////
     248// The following function read a data field (from one to four bytes)
     249// from an unsigned char[] buffer, taking endianness into account.
     250// The analysed field is defined by the "offset" and "size" arguments.
     251//////////////////////////////////////////////////////////////////////////////
     252
     253static unsigned int _read_entry( unsigned int    offset,
     254                                 unsigned int    size,
     255                                 unsigned char*  buffer,
     256                                 unsigned int    little_indian );
     257
     258//////////////////////////////////////////////////////////////////////////////////
     259// The following function returns the lba of first sector in DATA region
     260// from the cluster index. The cluster index must be larger than 2.
     261//////////////////////////////////////////////////////////////////////////////////
     262
     263static unsigned int _cluster_to_lba( unsigned int cluster );
     264
     265//////////////////////////////////////////////////////////////////////////////////
     266// The following function returns in the "nb_entries" argument the number of files
     267// (or directories) contained in a directory identidied by the "inode " pointer.
     268// It returns  0 if success.
     269// It returns  1 if error.
     270//////////////////////////////////////////////////////////////////////////////////
     271
     272static unsigned int _get_nb_entries( fat_inode_t*   inode,
     273                                     unsigned int*  nb_entries );
     274
     275//////////////////////////////////////////////////////////////////////////////////
     276// The following function search in the directory identified by the "parent"
     277// inode pointer a child (file or directory) identified by its "name".
     278// It returns in the "inode" argument the searched child inode pointer.
     279// If the searched name is not found in the Inode-Tree, the function access
     280// the "file_cache" associated to the parent directory.
     281// If the child exist on block device, the Inode-Tree is updated, and
     282// a success code is returned.
     283// If the file/dir does not exist on block device, a error code is returned.
     284// It returns 0 if inode found.
     285// It returns 1 if inode not found.
     286// It returns 2 if error in cache access.
     287//////////////////////////////////////////////////////////////////////////////////
     288
     289static unsigned int _get_child_from_parent( fat_inode_t*   parent,
     290                                            char*          name,
     291                                            fat_inode_t**  inode );
     292
     293/////////////////////////////////////////////////////////////////////////////////
     294// For a file (or a directory) identified by the "pathname" argument, the
     295// following function returns in the "inode" argument the inode pointer
     296// associated to the searched file (or directory), with code (0).
     297// If the searched file (or directory) is not found, but the parent directory
     298// is found, it returns in the "inode" argument the pointer on the parent inode,
     299// with code (1).  Finally, code (2) and code (3) are error codes.
     300// Both the Inode-Tree and the involved Cache-Files are updated from the block
     301// device in case of miss on one inode during the search in path.
     302// Neither the Fat-Cache, nor the block device are updated.
     303// It returns 0 if searched inode found
     304// It returns 1 if searched inode not found but parent directory found
     305// It returns 2 if searched inode not found and parent directory not found
     306// It returns 3 if one name too long
     307/////////////////////////////////////////////////////////////////////////////////
     308
     309static unsigned int _get_inode_from_path( char*          pathname,
     310                                          fat_inode_t**  inode );
     311
     312//////////////////////////////////////////////////////////////////////////////////
     313// This function computes the length and the number of LFN entries required
     314// to store a node name in the "length" and "nb_lfn" arguments.
     315// Short name (less than 13 characters) require 1 LFN entry.
     316// Medium names (from 14 to 26 characters require 2 LFN entries.
     317// Large names (up to 31 characters) require 3 LFN entries.
     318// It returns 0 if success.
     319// It returns 1 if length larger than 31 characters.
     320//////////////////////////////////////////////////////////////////////////////////
     321
     322static unsigned int _check_name_length( char* name,
     323                                        unsigned int* length,
     324                                        unsigned int* nb_lfn );
     325
     326//////////////////////////////////////////////////////////////////////////////////
     327// For a node identified by the "inode" argument, this function updates the
     328// "size" and "cluster" values in the entry of the parent directory File-Cache.
     329// It set the dirty bit in the modified buffer of the parent directory File-Cache.
     330//////////////////////////////////////////////////////////////////////////////////
     331
     332static unsigned int _update_dir_entry( fat_inode_t*  inode );
     333
     334//////////////////////////////////////////////////////////////////////////////////
     335// The following function add new "child" in Cache-File of "parent" directory.
     336// It access the File_Cache associated to the parent directory, and scan the
     337// clusters allocated to this directory to find the NO_MORE entry.
     338// This entry will be the first modified entry in the directory.
     339// Regarding the name storage, it uses LFN entries for all names.
     340// Therefore, it writes 1, 2, or 3 LFN entries (depending on the child name
     341// actual length, it writes one NORMAL entry, and writes the new NOMORE entry.
     342// It updates the dentry field in the child inode.
     343// It set the dirty bit for all modified File-Cache buffers.
     344// The block device is not modified by this function.
     345//////////////////////////////////////////////////////////////////////////////////
     346
     347static unsigned int _add_dir_entry( fat_inode_t* child,
     348                                    fat_inode_t* parent );
     349
     350//////////////////////////////////////////////////////////////////////////////////
     351// The following function invalidates all dir_entries associated to the "inode"
     352// argument from its parent directory.
     353// It set the dirty bit for all modified buffers in parent directory Cache-File.
     354// The inode itself is not modified by this function.
     355// The block device is not modified by this function.
     356//////////////////////////////////////////////////////////////////////////////////
     357
     358static unsigned int _remove_dir_entry( fat_inode_t*  inode );
     359
     360//////////////////////////////////////////////////////////////////////////////////
     361// The following function add the special entries "." and ".." in the File-Cache
     362// of the directory identified by the "child" argument.
     363// The parent directory is defined by the "parent" argument.
     364// The child directory File-Cache is supposed to be empty.
     365// We use two NORMAL entries for these "." and ".." entries.
     366// The block device is not modified by this function.
     367//////////////////////////////////////////////////////////////////////////////////
     368
     369static void _add_special_directories( fat_inode_t* child,
     370                                      fat_inode_t* parent );
     371
     372//////////////////////////////////////////////////////////////////////////////////
     373// The following function releases all clusters allocated to a file or directory,
     374// from the cluster index defined by the "cluster" argument, until the end
     375// of the FAT linked list.
     376// It calls _get_fat_entry() and _set_fat_entry() functions to scan the FAT,
     377// and to update the clusters chaining.
     378// The FAT region on block device is updated.
     379// It returns 0 if success.
     380// It returns 1 if error.
     381//////////////////////////////////////////////////////////////////////////////////
     382
     383static unsigned int _clusters_release( unsigned int cluster );
     384
     385//////////////////////////////////////////////////////////////////////////////////
     386// This function allocate "nb_clusters_more" new clusters to a file (or directory)
     387// identified by the "inode" pointer. It allocates also the associated buffers
     388// and buffer descriptors in the Cache-File.
     389// It calls _get_fat_entry() and _set_fat_entry() functions to update the
     390// clusters chaining in the Cache-Fat. The FAT region on block device is updated.
     391// It returns 0 if success.
     392// It returns 1 if error.
     393//////////////////////////////////////////////////////////////////////////////////
     394
     395static unsigned int _clusters_allocate( fat_inode_t* inode,
     396                                        unsigned int nb_clusters_current,
     397                                        unsigned int nb_clusters_more );
     398
     399//////////////////////////////////////////////////////////////////////////////////
     400// This recursive function scan one File-Cache (or Fat-Cache) from root to leaves.
     401// The cache 64-Tree infrastructure is kept, but all memory allocated for 4 Kbytes
     402// buffers, and for buffer descriptors (in leaves) is released.
     403// The cache is identified by the "root" an "levels" arguments.
     404// It should not contain any dirty clusters.
     405// It returns 0 if success.
     406// It returns 1 if error.
     407//////////////////////////////////////////////////////////////////////////////////
     408
     409static unsigned int _release_cache_memory( fat_cache_node_t*  root,
     410                                           unsigned int       levels );
     411
     412//////////////////////////////////////////////////////////////////////////////////
     413// The following function allocates and initializes a new inode,
     414// using the values defined by the arguments.
     415// If the "cache_allocate" argument is true ans empty cache is allocated.
     416// The Fat-Cache is initialised as empty: all children set to NULL.
     417// It returns a pointer on the new inode.
     418//////////////////////////////////////////////////////////////////////////////////
     419
     420static fat_inode_t* _allocate_one_inode( char*        name,
     421                                         unsigned int is_dir,
     422                                         unsigned int cluster,
     423                                         unsigned int size,
     424                                         unsigned int count,
     425                                         unsigned int dentry,
     426                                         unsigned int cache_allocate );
     427
     428//////////////////////////////////////////////////////////////////////////////////
     429// The following function allocates one 4 Kbytes buffer and associated cluster
     430// descriptor for the file (or directory) identified by the "inode" argument,
     431// and updates the Cache_File slot identified by the "cluster_id" argument.
     432// The File-Cache slot must be empty.
     433// It updates the cluster descriptor, using the "cluster" argument, that is
     434// the cluster index in FAT.  The cluster descriptor dirty field is set.
     435// It traverse the 64-tree Cache-file from top to bottom to find the last level.
     436//////////////////////////////////////////////////////////////////////////////////
     437
     438static void _allocate_one_buffer( fat_inode_t*    inode,
     439                                  unsigned int    cluster_id,
     440                                  unsigned int    cluster );
     441
     442//////////////////////////////////////////////////////////////////////////////////
     443// The following function allocates one free cluster from the FAT "heap" of free
     444// clusters, and returns the cluster index in the "cluster" argument.
     445// It updates the FAT slot, and the two FAT global variables: first_free_cluster,
     446// and free_clusters_number.
     447// It returns O if success.
     448// It returns 1 if error.
     449//////////////////////////////////////////////////////////////////////////////////
     450
     451static unsigned int _allocate_one_cluster( unsigned int*  cluster );
     452
     453/////////////////////////////////////////////////////////////////////////////
     454// This function remove from the file system a file or a directory
     455// identified by the "inode" argument.
     456// The remove condition must be checked by the caller.
     457// The relevant lock(s) must have been taken by te caller.
     458// It returns O if success.
     459// It returns 1 if error.
     460/////////////////////////////////////////////////////////////////////////////
     461
     462static unsigned int _remove_node_from_fs( fat_inode_t* inode );
     463
     464/////////////////////////////////////////////////////////////////////////////
     465// This function return the cluster index and the size for a file
     466// identified by the "pathname" argument, scanning directly the block
     467// device DATA region.
     468// It is intended to be called only by the _fat_load_no_cache() function,
     469// it does not use the dynamically allocated File Caches, but uses only
     470// the 4 Kbytes _fat_buffer_data.
     471// It returns 0 if success.
     472// It returns 1 if error.
     473/////////////////////////////////////////////////////////////////////////////
     474
     475static unsigned int _file_info_no_cache( char*          pathname,
     476                                         unsigned int*  file_cluster,
     477                                         unsigned int*  file_size );
     478
     479/////////////////////////////////////////////////////////////////////////////
     480// This function scan directly the FAT region on the block device,
     481// and returns in the "next" argument the value stored in the fat slot
     482// identified by the "cluster" argument.
     483// It is intended to be called only by the _fat_load_no_cache() function,
     484// as it does not use the dynamically allocated Fat-Cache, but uses only
     485// the 4 Kbytes _fat_buffer_fat.
     486// It returns 0 if success.
     487// It returns 1 if error.
     488/////////////////////////////////////////////////////////////////////////////
     489
     490static unsigned int _next_cluster_no_cache( unsigned int   cluster,
     491                                            unsigned int*  next );
     492
     493
     494//////////////////////////////////////////////////////////////////////////////////
     495// The following functions return the length or the size of a FAT field,
     496// identified by an (offset,length) mnemonic defined in the fat32.h file.
     497//////////////////////////////////////////////////////////////////////////////////
     498
     499static inline int get_length( int offset , int length ) { return length; }
     500
     501static inline int get_offset( int offset , int length ) { return offset; }
     502
     503
     504
     505
     506
     507//////////////////////////////////////////////////////////////////////////////////
     508//////////////////////////////////////////////////////////////////////////////////
     509//                  Static functions definition
     510//////////////////////////////////////////////////////////////////////////////////
     511//////////////////////////////////////////////////////////////////////////////////
     512
     513#if GIET_DEBUG_FAT
     514///////////////////////////////////////////////////
     515static void _display_one_block( unsigned char* buf,
     516                                char*          string,
     517                                unsigned int   block_id )
     518{
     519    unsigned int line;
     520    unsigned int word;
     521
     522    _printf("\n***  <%s>  block %x  ***********************************\n",
     523            string , block_id );
     524
     525    for ( line = 0 ; line < 16 ; line++ )
     526    {
     527        // display line index
     528        _printf("%x : ", line );
     529
     530        // display 8*4 bytes hexa
     531        for ( word=0 ; word<8 ; word++ )
     532        {
     533            unsigned int byte  = (line<<5) + (word<<2);
     534            unsigned int hexa  = (buf[byte  ]<<24) |
     535                                 (buf[byte+1]<<16) |
     536                                 (buf[byte+2]<< 8) |
     537                                 (buf[byte+3]      );
     538            _printf(" %X |", hexa );
     539        }
     540        _printf("\n");
     541    }
     542    _printf("*******************************************************************\n");
     543} // end _display_one_block() 
     544#endif
     545
     546
     547
     548#if GIET_DEBUG_FAT
     549/////////////////////////////////////
     550static void _display_fat_descriptor()
     551{
     552    _printf("\n###############  FAT DESCRIPTOR  ################################" 
     553            "\nFAT initialised                  %x"
     554            "\nBlock Size  (bytes)              %x"
     555            "\nCluster Size  (bytes)            %x"
     556            "\nFAT region first lba             %x"
     557            "\nFAT region size (blocks)         %x"
     558            "\nDATA region first lba            %x"
     559            "\nDATA region size (blocks)        %x"
     560            "\nNumber of free clusters          %x"
     561            "\nFirst free cluster index         %x"
     562            "\nFat_cache_levels                 %d"
     563            "\n#################################################################\n",
     564            _fat.initialised,
     565            _fat.sector_size,
     566            _fat.cluster_size,
     567            _fat.fat_lba,
     568            _fat.fat_sectors,
     569            _fat.data_lba,
     570            _fat.data_sectors,
     571            _fat.free_clusters_number,
     572            _fat.first_free_cluster,
     573            _fat.fat_cache_levels );
     574
     575} // end _display_fat_descriptor()
     576#endif
     577
     578
     579
     580#if GIET_DEBUG_FAT
     581////////////////////////////////////////////////////////
     582static void _display_clusters_list( fat_inode_t* inode )
     583{
     584    _printf("\n**************** clusters for <%s> ***********************\n", inode->name );
     585    unsigned int next;
     586    unsigned int n       = 0;
     587    unsigned int current = inode->cluster;
     588    while( (current < END_OF_CHAIN_CLUSTER_MIN) && (n < 1024) )
     589    {
     590        _get_fat_entry( current , &next );
     591        _printf(" > %X", current );
     592        n++;
     593        if ( (n & 0x7) == 0 ) _printf("\n");
     594        current = next;
     595    }
     596    _printf("\n");
     597}  // end _display_clusters_list()
     598#endif
     599
     600
     601
     602/////////////////////////////////////////////////////////////////////////////////
     603static int _fat_ioc_access( unsigned int use_irq,       // descheduling if non zero
     604                            unsigned int to_mem,        // read / write
     605                            unsigned int lba,           // first sector on device
     606                            unsigned int buf_vaddr,     // memory buffer vaddr
     607                            unsigned int count )        // number of sectors
    53608{
    54609    // compute memory buffer physical address
     
    57612
    58613    if ( ((_get_mmu_mode() & 0x4) == 0 ) || USE_IOC_RDK )  // identity
    59     {
     614    { 
    60615        buf_paddr = (unsigned long long)buf_vaddr;
    61616    }
     
    65620    }
    66621
    67 #if GIET_DEBUG_FAT
    68 unsigned int procid  = _get_procid();
    69 unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
    70 unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
    71 unsigned int p       = procid & ((1<<P_WIDTH)-1);
    72 if ( _get_proctime() > GIET_DEBUG_FAT )
    73 _printf("\n[DEBUG FAT] P[%d,%d,%d] enters _fat_ioc_access() at cycle %d\n"
     622#if (GIET_DEBUG_FAT & 1)
     623if ( _get_proctime() > GIET_DEBUG_FAT )
     624_printf("\n[DEBUG FAT] _fat_ioc_access() : enters at cycle %d\n"
    74625        "  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 );
     626        _get_proctime(), to_mem, buf_vaddr, buf_paddr, count, lba );
    76627#endif
    77628
     
    100651
    101652
    102 //////////////////////////////////////////////////////////////////////////////////
    103 // This function displays the content of the FAT cache
    104 //////////////////////////////////////////////////////////////////////////////////
    105 #if GIET_DEBUG_FAT
    106 static
    107 void _display_fat_cache()
    108 {
    109     unsigned int line;
    110     unsigned int word;
    111     unsigned int temp[9];
    112 
    113     temp[8] = 0;
    114 
    115     _puts("\n*********************** fat_cache_lba = ");
    116     _putx( _fat.cache_lba );
    117     _puts(" *****************************\n");
    118 
    119     for ( line = 0 ; line < 16 ; line++ )
    120     {
    121         // display line index
    122         _putx( line );
    123         _puts(" : ");
    124 
    125         // display 8*4 bytes hexa
    126         for ( word=0 ; word<8 ; word++ )
    127         {
    128             unsigned int byte  = (line<<5) + (word<<2);
    129             unsigned int hexa  = (_fat.fat_cache[byte  ]<<24) |
    130                                  (_fat.fat_cache[byte+1]<<16) |
    131                                  (_fat.fat_cache[byte+2]<< 8) |
    132                                  (_fat.fat_cache[byte+3]);
    133             _putx( hexa );
    134             _puts(" | ");
    135 
    136             // prepare display ascii
    137             temp[word] = _fat.fat_cache[byte]         |
    138                          (_fat.fat_cache[byte+1]<<8)  |
    139                          (_fat.fat_cache[byte+2]<<16) |
    140                          (_fat.fat_cache[byte+3]<<24) ;
    141         }
    142        
    143         // display data ascii
    144         _puts( (char*)temp );
    145         _puts("\n");
    146     }
    147     _puts("***************************************************************************\n");
    148 
    149 } // end _display_fat_cache() 
    150 #endif
    151 
    152 //////////////////////////////////////////////////////////////////////////////////
    153 // This function displays the FAT descriptor.
    154 //////////////////////////////////////////////////////////////////////////////////
    155 #if GIET_DEBUG_FAT
    156 static
    157 void _fat_print()
    158 {
    159     _printf("\n########################## FAT32 ################################" 
    160             "\nFAT initialised                  %x"
    161             "\nSector Size  (bytes)             %x"
    162             "\nSectors per cluster              %x"
    163             "\nFAT region first lba             %x"
    164             "\nData region first lba            %x"
    165             "\nNumber of sectors for one FAT    %x"
    166             "\nNumber of free clusters          %x"
    167             "\nLast allocated cluster           %x"
    168             "\n#################################################################\n",
    169             _fat.initialised,
    170             _fat.sector_size,
    171             _fat.sectors_per_cluster,
    172             _fat.fat_lba,
    173             _fat.data_lba,
    174             _fat.fat_sectors,
    175             _fat.number_free_cluster,
    176             _fat.last_cluster_allocated );
    177 } // end _fat_print()
    178 #endif
    179 
    180 //////////////////////////////////////////////////////////////////////////////////
    181 // This function returns the length of a FAT field. This field is identified
    182 // by an (offset,length) mnemonic defined in fat32.h file.
    183 //////////////////////////////////////////////////////////////////////////////////
    184 static inline
    185 int get_length( int offset,
    186                 int length )
    187 {
    188     return length;
     653
     654
     655/////////////////////////////////////////////////////////////////////
     656static inline unsigned int _get_levels_from_size( unsigned int size )
     657{
     658    if      ( size <= (1<<18) ) return 1;     // 64 clusters == 256 Kbytes
     659    else if ( size <= (1<<24) ) return 2;     // 64 * 64 clusters => 16 Mbytes
     660    else if ( size <= (1<<30) ) return 3;     // 64 * 64 * 64 cluster => 1 Gbytes
     661    else                        return 4;     // 64 * 64 * 64 * 64 clusters
    189662}
    190663
    191 //////////////////////////////////////////////////////////////////////////////
    192 // Write one 32 bits word "value" in a char[] buffer.
    193 // The modified field in buffer is defined by the offset and size arguments.
    194 //////////////////////////////////////////////////////////////////////////////
    195 static
    196 void _write_entry( unsigned int   offset,
    197                    unsigned int   size,
    198                    char*          buffer,
    199                    unsigned int   value )
    200 {
    201     unsigned int turn = 0;
    202     unsigned int res  = value;
    203     unsigned int mask = 0x000000ff;
    204 
    205     while( turn != size - 1 )
    206     {
    207         buffer[ offset + turn ] = res & mask;
    208         res = res >> 8;
    209         turn++;
    210     }
    211     buffer[offset + turn] = res & mask;
     664
     665
     666////////////////////////////////////////////////////////
     667static unsigned int _read_entry( unsigned int    offset,
     668                                 unsigned int    size,
     669                                 unsigned char*  buffer,
     670                                 unsigned int    little_endian )
     671{
     672    unsigned int n;
     673    unsigned int res  = 0;
     674
     675    if ( little_endian)
     676    {
     677        for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
     678    }
     679    else
     680    {
     681        for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
     682    }
     683    return res;
     684
     685}  // end _read_entry
     686
     687
     688
     689//////////////////////////////////////////////////////////////////
     690static inline unsigned int _cluster_to_lba( unsigned int cluster )       
     691{
     692    if ( cluster < 2 )
     693    {
     694        _printf("\n[FAT ERROR] in _cluster_to_lba() cluster smaller than 2\n");
     695        _exit();
     696    }
     697
     698   return  ((cluster - 2) << 3) + _fat.data_lba;
    212699}
    213700
    214 //////////////////////////////////////////////////////////////////////////////
    215 // Read one 32 bits word in a char[] buffer, taking endianness into account.
    216 // The analysed field in buffer is defined by the offset and size arguments.
    217 //////////////////////////////////////////////////////////////////////////////
    218 static
    219 unsigned int _read_entry( unsigned int   offset,
    220                           unsigned int   size,
    221                           char*          buffer,
    222                           unsigned int   little_indian )
    223 {
    224     unsigned int turn;
    225     unsigned int res  = 0;
    226     unsigned int mask = 0x000000ff;
    227 
    228     if( little_indian )
    229     {
    230         turn = size;
    231         while( turn != 1 )
    232         {
    233             res = res | (buffer[offset + (turn-1)] & mask);
    234             res = res << 8;
    235             turn--;
    236         }
    237         res = (buffer[offset + (turn-1)] & mask) | res;
    238     }
    239     else
    240     {
    241         turn = 0;
    242         while( turn != size - 1 )
    243         {
    244 
    245             res = res  | (buffer[ offset + turn ] & mask );
    246             res = res << 8;
    247             turn++;
    248         }
    249         res = res | (buffer[offset + turn] & mask);
    250     }
    251     return res;
    252 }
    253 
    254 //////////////////////////////////////////////////////////////////////////////////
    255 // This function retuns the cluster index from the lba of a DATA sector.
    256 // The lba must be larger than the lba of the first DATA sector.
    257 // The DATA region indexing starts a cluster 2.
    258 //////////////////////////////////////////////////////////////////////////////////
    259 static inline
    260 unsigned int lba_to_cluster( unsigned int lba )                   
    261 {
    262    if (lba < _fat.data_lba ) return 0;
    263 
    264    return ( (lba - _fat.data_lba) / _fat.sectors_per_cluster) + 2;
    265 }
    266 
    267 //////////////////////////////////////////////////////////////////////////////////
    268 // This function retuns the lba of first sector in DATA region
    269 // from the cluster index. The cluster index must be larger than 2.
    270 //////////////////////////////////////////////////////////////////////////////////
    271 static inline
    272 unsigned int cluster_to_lba( unsigned int cluster )       
    273 {
    274    if ( cluster < 2 ) return 0;
    275 
    276    return  (_fat.sectors_per_cluster * (cluster - 2)) + _fat.data_lba;
    277 }
    278 
    279 /////////////////////////////////////////////////////////////////////////////////
    280 // This function search the FAT (using the FAT cache), and returns
    281 // the next cluster index from the current cluster index in the FAT.
    282 // remark: a sector of FAT contains 128 cluster indexes.
    283 /////////////////////////////////////////////////////////////////////////////////
    284 static
    285 unsigned int _get_next_cluster( unsigned int use_irq,
    286                                 unsigned int cluster )
    287 {
    288     // compute lba of the sector containing the cluster index
    289     unsigned int lba = _fat.fat_lba + (cluster / 128);
    290 
    291     if ( lba != _fat.cache_lba )      // miss in fat_cache
    292     {
    293         // access fat
    294         if( _fat_ioc_access( use_irq,
    295                              1,               // read
    296                              lba,
    297                              (unsigned int)_fat.fat_cache,
    298                              1 ) )            // one sector
    299         {
    300             _printf("[FAT_ERROR] in get_next_cluster_id() : cannot read block %x",
    301                     lba );
    302             return 1;
    303         }
    304         _fat.cache_lba = lba;
    305     }
    306 
    307     unsigned int next = _read_entry( ((cluster % 128) * 4),
    308                                      4,
    309                                      _fat.fat_cache,
    310                                      1 );
    311 #if GIET_DEBUG_FAT
    312 unsigned int procid  = _get_procid();
    313 unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
    314 unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
    315 unsigned int p       = procid & ((1<<P_WIDTH)-1);
    316 if ( _get_proctime() > GIET_DEBUG_FAT )
    317 _printf("\n[DEBUG FAT] P[%d,%d,%d] in _get_next_cluster() :  next = %x\n",
    318         x , y , p , next );
    319 if ( (_get_proctime() > GIET_DEBUG_FAT) && (GIET_DEBUG_FAT & 0x1) )
    320 _display_fat_cache();
    321 #endif
    322 
    323     return next;
    324 }
    325701
    326702//////////////////////////////////////////////////////
    327 static inline unsigned char to_upper(unsigned char c)
     703static inline unsigned char _to_upper(unsigned char c)
    328704{
    329705   if (c >= 'a' && c <= 'z') return (c & ~(0x20));
     
    331707}
    332708
    333 ////////////////////////////////////////////////////////////////
    334 // This function is a filter:
    335 // Return the c character if c is a legal short name character
    336 // Return the '_' character if c is illegal
    337 ////////////////////////////////////////////////////////////////
    338 static
    339 unsigned char illegal_short(unsigned char c)
    340 {
    341    const unsigned char illegal_char [] =";+=[]’,\"*\\<>/?:|\0";
    342    short i = 0;
    343    while (illegal_char[i]!='\0')
    344    {
    345       if (c == illegal_char[i])
    346          return '_';
    347       i++;
    348    }
    349    return c;
    350 }
    351 
    352 /////////////////////////////////////////////////////////////////////////////////
    353 // This function test if the string argument is a legal SFN (Short File Name)
    354 // and copies this name (removing the .) in the sfn_string argument.
    355 // Criteria for a Short File Name are:
    356 // - separator is '.' (extension is not mandatory)
    357 // - 1 <= name length <= 8
    358 // - 0 <= extension length <= 3
    359 // - no illegal character (see illega_short() function)
    360 // Return 1 if it string is a legal SFN
    361 // Return 0 if not legal SFN
    362 /////////////////////////////////////////////////////////////////////////////////
    363 static
    364 int is_short( char* string,
    365               char* sfn_string)
    366 {
    367     int s_size   = 0;
    368     int dot_ext  = 0;       // dot offset in the filename
    369     int name_len = 0;       // length of file name
    370     int ext_len  = 0;       // length of extension
    371     int i        = 0;
    372     int sc_i     = 0;
    373     char ch;
    374 
    375     if(string[0] == '.' && string[1] == '\0')
    376     {
    377         sfn_string[0] = '.';
    378         return 1;
    379     }
    380     if(string[0] == '.' && string[1] == '.' && string[2] == '\0')
    381     {
    382         sfn_string[0] = '.';
    383         sfn_string[1] = '.';
    384         return 1;
    385     }
    386     sfn_string[11] = '\0';
    387     while (string[s_size] != '\0')
    388     {
    389         if (string[s_size] == '.')
    390         {
    391             dot_ext = s_size;
    392             ext_len = -1;
    393         }
    394         ext_len++;
    395         s_size++;
    396     }
    397     if (dot_ext != 0)
    398     {
    399         name_len = s_size - ext_len - 1;
    400     }
    401     else
    402     {
    403         name_len = s_size;
    404         ext_len = 0;
    405     }
    406     if ( ext_len > 3 || ( name_len > 8))
    407     {
    408         return 0;
    409     }
    410     if (dot_ext != 0)
    411     {
    412         while (i != ext_len)
    413         {
    414             ch = to_upper(string[dot_ext + 1 + i]);
    415             ch = illegal_short(ch);
    416             sfn_string[8+i] = ch;
    417             i++;
    418         }
    419     }
    420     i = 0;
    421     sc_i = 0;
    422     while (i!= name_len)
    423     {
    424         ch = to_upper(string[i]);
    425         ch = illegal_short(ch);
    426         if (ch != '.') sfn_string[sc_i++] = ch;
    427         i++;
    428     }
    429     return 1;
    430 }
    431 
    432 ///////////////////////////////////////////////////////////////////////
    433 // This function analyses the pathname argument, from the character
    434 // defined by the *nb_read argument.
    435 // It copies the found name (between '/') in the name[] buffer,
    436 // and updates the nb_read argument.
    437 // Return 1 if name found, Return 0 if NUL character found,
    438 ///////////////////////////////////////////////////////////////////////
    439 static
    440 int get_name_from_path( char*          pathname,
    441                         char*          name,
    442                         unsigned int*  nb_read )       
    443 {
    444     if ( pathname[*nb_read] == 0 ) return 0;
    445 
    446     int i = (pathname[*nb_read] == '/')? (*nb_read) + 1 : *nb_read;
    447     int j = 0;
     709
     710
     711///////////////////////////////////////////////////////////////////////////
     712static unsigned int _get_name_from_path( char*          pathname,  // input
     713                                         char*          name,      // output
     714                                         unsigned int*  nb_read )  // input & output   
     715{
     716    // skip leading "/" character
     717    if ( pathname[*nb_read] == '/' ) *nb_read = *nb_read + 1;
     718
     719    // initialises current indexes
     720    unsigned int i = *nb_read;
     721    unsigned int j = 0;
    448722   
    449     while(pathname[i] != '/' && pathname[i] != '\0')
    450     {
    451         name[j] = pathname[i];   
    452         j++;
    453         i++;
    454     }
     723    while ( (pathname[i] != '/') && (pathname[i] != 0) )
     724    {
     725        name[j++] = pathname[i++];   
     726        if ( j > NAME_MAX_SIZE ) return 1;
     727    }
     728
     729    // set end of string
    455730    name[j] = 0;
    456731
     732    // skip trailing "/" character
    457733    if ( pathname[i] == '/' ) *nb_read += j+1;
    458734    else                      *nb_read += j;
    459735
    460     return 1;
     736    return 0;
    461737}
    462738
     739
     740
     741////////////////////////////////////////////////////////////////////
     742static unsigned int _get_last_name( char*   pathname,       // input
     743                                    char*   name )          // output
     744{
     745    unsigned int nb_read = 0;     
     746    while ( pathname[nb_read] != 0 )
     747    {
     748        if ( _get_name_from_path( pathname, name, &nb_read ) ) return 1;
     749    }
     750
     751    return 0;
     752}   // end _get_last_name()
     753
     754
     755
    463756////////////////////////////////////////////////////////////////////////////////
    464 static int get_name_from_short( char* dir_entry,     // input:  SFN dir_entry
    465                                 char* entry_name )   // output: name
     757static void _get_name_from_short( unsigned char* buffer,  // input:  SFN dir_entry
     758                                  char*          name )   // output: name
    466759{
    467760    unsigned int i   = 0;
     
    470763    while ( i < length )
    471764    {
    472         entry_name[i] = dir_entry[i];
     765        name[i] = buffer[i];
    473766        i++;
    474767    }
    475     entry_name[i] = '\0';
    476 
    477     return i;
     768    name[i] = 0;
    478769}
    479770
    480771///////////////////////////////////////////////////////////////////////////////
    481 static int get_name_from_long( char *dir_entry,    // input : LFN dir_entry
    482                                char *entry_name )   // output : name
    483 {
    484     unsigned int   entry_name_offset   = 0;
    485     unsigned int   dir_entry_offset    = get_length(LDIR_ORD);
     772static void _get_name_from_long( unsigned char*  buffer, // input : LFN dir_entry
     773                                 char*           name )  // output : name
     774{
     775    unsigned int   name_offset         = 0;
     776    unsigned int   buffer_offset       = get_length(LDIR_ORD);
    486777    unsigned int   l_name_1            = get_length(LDIR_NAME_1);
    487778    unsigned int   l_name_2            = get_length(LDIR_NAME_2);
     
    495786    unsigned int eof          = 0;
    496787
    497     while ( (dir_entry_offset != DIR_ENTRY_SIZE)  && (!eof) )
     788    while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) )
    498789    {
    499790        while (j != l_name_1 && !eof )
    500791        {
    501             if ( (dir_entry[dir_entry_offset] == 0x00) ||
    502                  (dir_entry[dir_entry_offset] == 0xFF) )
     792            if ( (buffer[buffer_offset] == 0x00) ||
     793                 (buffer[buffer_offset] == 0xFF) )
    503794            {
    504795                eof = 1;
    505796                continue;
    506797            }
    507             entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
    508             dir_entry_offset += 2;
     798            name[name_offset] = buffer[buffer_offset];
     799            buffer_offset += 2;
    509800            j += 2;
    510             entry_name_offset++;
    511         }
    512 
    513         dir_entry_offset += (l_attr + l_type + l_chksum);
     801            name_offset++;
     802        }
     803
     804        buffer_offset += (l_attr + l_type + l_chksum);
    514805        j = 0;
    515806
    516807        while (j != l_name_2 && !eof )
    517808        {
    518             if ( (dir_entry[dir_entry_offset] == 0x00) ||
    519                  (dir_entry[dir_entry_offset] == 0xFF) )
     809            if ( (buffer[buffer_offset] == 0x00) ||
     810                 (buffer[buffer_offset] == 0xFF) )
    520811            {
    521812                eof = 1;
    522813                continue;
    523814            }
    524             entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
    525             dir_entry_offset += 2;
     815            name[name_offset] = buffer[buffer_offset];
     816            buffer_offset += 2;
    526817            j += 2;
    527             entry_name_offset++;
    528         }
    529 
    530         dir_entry_offset += l_rsvd;
     818            name_offset++;
     819        }
     820
     821        buffer_offset += l_rsvd;
    531822        j = 0;
    532823
    533824        while (j != l_name_3 && !eof )
    534825        {
    535             if ( (dir_entry[dir_entry_offset] == 0x00) ||
    536                  (dir_entry[dir_entry_offset] == 0xFF) )
     826            if ( (buffer[buffer_offset] == 0x00) ||
     827                 (buffer[buffer_offset] == 0xFF) )
    537828            {
    538829                eof = 1;
    539830                continue;
    540831            }
    541             entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
    542             dir_entry_offset += 2;
     832            name[name_offset] = buffer[buffer_offset];
     833            buffer_offset += 2;
    543834            j += 2;
    544             entry_name_offset++;
    545         }
    546     }
    547     entry_name[entry_name_offset] = '\0';
    548 
    549     return entry_name_offset;
     835            name_offset++;
     836        }
     837    }
     838    name[name_offset] = 0;
    550839} // end get_name_from_long()
    551840
    552 ///////////////////////////////////////////////////////////////////////////////////
    553 // This function update a DIR_ENTRY, write a new value into a specific field
    554 // (ex : DIR_FILE_SIZE, when we want update the file size after a fat_write)
    555 // Return 0 in case of success, > 0 if failure.
    556 ///////////////////////////////////////////////////////////////////////////////////
    557 // TODO : make this function less complex
    558 ///////////////////////////////////////////////////////////////////////////////////
    559 static inline
    560 unsigned int _update_entry( unsigned int use_irq,
    561                             unsigned int fd_id,
    562                             unsigned int field,
    563                             unsigned int size,
    564                             unsigned int value )
    565 {
    566     char dir_entry[32];   // buffer to store a full directory_entry
    567     char name_entry[14];  // buffer to store a 13 characters (partial) name
    568     char file_name[256];  // buffer to store the name (not pathname) of the file
    569 
    570     char sfn_string[12]  = {[0 ... 10] = ' ', '\0'};     // buffer Short File Name
    571     unsigned int lba     = _fat.fd[fd_id].lba_dir_entry;  // Lba of file dir_entry
    572     unsigned int is_sfn;         
    573     unsigned int attr    = 0;                            // dir entry attribute
    574     unsigned int ord     = 0;                            // dir entry sequence
    575     unsigned int found   = 0;                            // name found
    576     unsigned int offset  = 0;                            // offset in fat_cache
    577     unsigned int i       = 0;
    578     unsigned int nb_read = 0;
    579 
    580     for ( i = 0 ; i < 32 ; i++ ) dir_entry[i]  = 0;
    581     for ( i = 0 ; i < 14 ; i++ ) name_entry[i] = 0;
    582    
    583     // Get the name of the file.
    584     while ( get_name_from_path( _fat.fd[fd_id].name, file_name, &nb_read ) )
    585     {
    586     }
    587 
    588     // Format file_name to SFN format
    589     is_sfn = is_short( file_name, sfn_string );
    590 
    591     // access FAT
    592     if ( _fat_ioc_access( use_irq,
    593                           1,               // read
    594                           lba,
    595                           (unsigned int)_fat.fat_cache,
    596                           1 ) )            // one sector
    597     {
    598         _printf("\n[FAT ERROR] in _update_entry() cannot read sector %x\n",
    599                 lba );
    600         return 1;
    601     }
    602     _fat.cache_lba = lba;
    603 
    604     // - the offset increment is an integer number of directory entry (32 bytes)
    605     // - the exit condition is success (name found) or failure (end of directory)
    606     while ( !found )
    607     {
    608         attr = _read_entry( DIR_ATTR, _fat.fat_cache + offset, 0 );
    609         ord  = _read_entry( LDIR_ORD, _fat.fat_cache + offset, 0 );
    610 
    611         if ( is_sfn == 1 )                                     // searched name is short
    612         {
    613             if      ( (ord != FREE_ENTRY ) &&
    614                     (ord != NO_MORE_ENTRY) &&
    615                     (attr == ATTR_LONG_NAME_MASK) )    // LFN entry : skipped
     841
     842
     843
     844////////////////////////////////////////////////////////////
     845static fat_inode_t* _allocate_one_inode( char*        name,
     846                                         unsigned int is_dir,
     847                                         unsigned int cluster,
     848                                         unsigned int size,
     849                                         unsigned int count,
     850                                         unsigned int dentry,
     851                                         unsigned int cache_allocate )
     852{
     853    fat_inode_t* new_inode  = _malloc( sizeof(fat_inode_t) );
     854
     855    new_inode->parent   = NULL;                 // set by _add_inode_in_tree()
     856    new_inode->next     = NULL;                 // set by _add_inode_in_tree()
     857    new_inode->child    = NULL;                 // set by _add_inode_in_tree()
     858    new_inode->cluster  = cluster;
     859    new_inode->size     = size;
     860    new_inode->cache    = NULL;
     861    new_inode->levels   = 0;
     862    new_inode->count    = count;
     863    new_inode->is_dir   = (is_dir != 0);
     864    new_inode->dentry   = dentry;             
     865
     866    _strcpy( new_inode->name , name ); 
     867
     868    if ( cache_allocate )
     869    {
     870        fat_cache_node_t* new_cache  = _malloc( sizeof(fat_cache_node_t) );
     871
     872        new_inode->cache    = new_cache;
     873        new_inode->levels   = _get_levels_from_size( size );
     874       
     875        unsigned int index;
     876        for ( index = 0 ; index < 64 ; index ++ )  new_cache->children[index] = NULL;
     877    }
     878
     879    return new_inode;
     880}   // end _allocate_one_inode()
     881
     882
     883
     884
     885////////////////////////////////////////////////////
     886static void _add_inode_in_tree( fat_inode_t*  child,
     887                                fat_inode_t*  parent )
     888{
     889    child->parent = parent;
     890    child->next   = parent->child;
     891    parent->child = child;
     892}   // end _add_inode-in_tree()
     893
     894
     895
     896
     897//////////////////////////////////////////////////////////
     898static void _remove_inode_from_tree( fat_inode_t*  inode )
     899{
     900    fat_inode_t*  current;
     901    fat_inode_t*  prev = inode->parent->child;
     902
     903    if ( inode == prev )  // removed inode is first in its linked list
     904    {
     905        inode->parent->child = inode->next;
     906    }
     907    else                  // removed inode is not the first
     908    {
     909        for( current = prev->next ; current ; current = current->next )
     910        {
     911            if ( current == inode )
    616912            {
    617                 offset     = offset + ((ord & 0xF) * DIR_ENTRY_SIZE);
    618                 continue;
     913                prev->next = current->next;
    619914            }
    620             else if ( (attr != ATTR_LONG_NAME_MASK) &&
    621                     (ord  != FREE_ENTRY) &&
    622                     (ord  != NO_MORE_ENTRY ) )         // SFN entry : checked
     915            prev = current;
     916        }   
     917    }   
     918}  // end _delete_one_inode()
     919
     920
     921
     922
     923//////////////////////////////////////////////////////////////////////
     924static unsigned int _get_buffer_from_cache( fat_inode_t*        inode,
     925                                            unsigned int        cluster_id,
     926                                            fat_cache_desc_t**  desc )
     927{
     928    // get cache pointer and levels
     929    fat_cache_node_t*   node;         // pointer on a 64-tree node
     930    unsigned int        level;        // cache level
     931
     932    if ( inode == NULL )   // searched cache is the Fat-Cache
     933    {
     934        node   = _fat.fat_cache_root;
     935        level  = _fat.fat_cache_levels;
     936
     937#if (GIET_DEBUG_FAT & 1)
     938if ( _get_proctime() > GIET_DEBUG_FAT )
     939_printf("\n[DEBUG FAT] _get_buffer_from_cache() : enters in FAT-Cache"
     940        " for cluster_id = %d\n", cluster_id );
     941#endif
     942
     943    }
     944    else                   // searched cache is a File-Cache
     945    {
     946        node   = inode->cache;
     947        level  = inode->levels;
     948
     949#if (GIET_DEBUG_FAT & 1)
     950if ( _get_proctime() > GIET_DEBUG_FAT )
     951_printf("\n[DEBUG FAT] _get_buffer_from_cache() : enters in File-Cache <%s>"
     952        " for cluster_id = %d\n", inode->name , cluster_id );
     953#endif
     954
     955    }
     956
     957    // search the 64-tree cache from top to bottom
     958    while ( level )
     959    {
     960        // compute child index at each level
     961        unsigned int index = (cluster_id >> (6*(level-1))) & 0x3F;
     962
     963        if ( level == 1 )        // last level => children are cluster descriptors
     964        {
     965            fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index];
     966
     967            if ( pdesc == NULL )      // miss
    623968            {
    624                 memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );   
     969                // allocate one cluster descriptor and one 4K buffer
     970                unsigned char* buf = _malloc( 4096 );
     971                pdesc              = _malloc( sizeof(fat_cache_desc_t) );
     972
     973                // get missing cluster index lba
     974                unsigned int lba;
     975                unsigned int next;
     976                unsigned int current = inode->cluster;
     977                unsigned int count   = cluster_id;
     978
     979                if ( inode == NULL )      // searched cache is the Fat-Cache
     980                {
     981
     982#if (GIET_DEBUG_FAT & 1)
     983if ( _get_proctime() > GIET_DEBUG_FAT )
     984_printf("\n[DEBUG FAT] _get_buffer_from_cache() : miss in FAT-Cache for cluster_id %d\n",
     985        cluster_id );
     986#endif
     987                    lba = _fat.fat_lba + (cluster_id << 3);
     988                }
     989                else                      // searched cache is a File-Cache
     990                {
     991
     992#if (GIET_DEBUG_FAT & 1)
     993if ( _get_proctime() > GIET_DEBUG_FAT )
     994_printf("\n[DEBUG FAT] _get_buffer_from_cache() : miss in File-Cache <%s> "
     995        "for cluster_id %d\n", inode->name, cluster_id );
     996#endif
     997                    while ( count )
     998                    {
     999                        if ( _get_fat_entry( current , &next ) ) return 1;
     1000                        current = next;
     1001                        count--;
     1002                    }
     1003                    lba = _cluster_to_lba( current );
     1004                }
     1005
     1006                // load one cluster (8 blocks) from block device
     1007                if ( _fat_ioc_access( 1,         // descheduling
     1008                                      1,         // to memory
     1009                                      lba,
     1010                                      (unsigned int)buf,
     1011                                      8 ) )
     1012                {
     1013                    _printf("\n[FAT ERROR] in _get_buffer_from_cache()"
     1014                            " : cannot access block device for lba = %x\n", lba );
     1015                    return 1;
     1016                }
     1017
     1018                // update cache and buffer descriptor
     1019                node->children[index] = pdesc;
     1020                pdesc->lba     = lba;
     1021                pdesc->buffer  = buf;
     1022                pdesc->dirty   = 0;
     1023
     1024#if (GIET_DEBUG_FAT & 1)
     1025if ( _get_proctime() > GIET_DEBUG_FAT )
     1026_printf("\n[DEBUG FAT] _get_buffer_from_cache() : buffer loaded from device"
     1027        " at vaddr = %x\n", (unsigned int)buf );
     1028#endif
    6251029            }
    626             else if (ord == NO_MORE_ENTRY )            // end of directory : return
     1030
     1031            // return pdesc pointer
     1032            *desc = pdesc;
     1033
     1034            // prepare next iteration
     1035            level--;
     1036        }
     1037        else                      // not last level => children are 64-tree nodes
     1038        {
     1039            fat_cache_node_t* child = (fat_cache_node_t*)node->children[index];
     1040            if ( child == NULL )  // miss
    6271041            {
    628                 _printf("\n[FAT ERROR] in _update_entry() : reaches end\n");
    629                 return 1;
     1042                // allocate a cache node if miss
     1043                child = (fat_cache_node_t*)_malloc( sizeof(fat_cache_node_t) );
     1044                node->children[index] = child;   
    6301045            }
    631             else                                                                           // free entry : skipped
    632             {
    633                 offset = offset + DIR_ENTRY_SIZE;
    634                 continue;
    635             }
    636         }
    637         else                                           // searched name is long
    638         {
    639             if      ( (attr == ATTR_LONG_NAME_MASK) &&
    640                     (ord != FREE_ENTRY) &&
    641                     (ord != NO_MORE_ENTRY) )           // LFN entry : checked
    642             {
    643                 memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );   
    644             }
    645             else if ( (attr != ATTR_LONG_NAME_MASK) &&
    646                     (ord  != FREE_ENTRY) &&
    647                     (ord  != NO_MORE_ENTRY))               // SFN entry : skipped
    648             {
    649                 offset = offset + DIR_ENTRY_SIZE;
    650                 continue;
    651             }
    652             else if (ord == NO_MORE_ENTRY )                        // end of directory : return
    653             {
    654                 _printf("\n[FAT ERROR] in _update_entry() reaches end\n");
    655                 return 1;
    656             }
    657             else                                       // free entry : skipped
    658             {
    659                 offset = offset + DIR_ENTRY_SIZE;
    660                 continue;
    661             }
    662         }
    663 
    664         // testing the name extracted from dir entry
    665 
    666         if ( is_sfn == 1 )                             // searched name is short
    667         {
    668             get_name_from_short( dir_entry, name_entry );
    669 
    670             if ( _strncmp( (char*)sfn_string, (char*)name_entry, 13 ) == 0 )
    671             {
    672                 _write_entry(offset + field, size, _fat.fat_cache, value);
    673                 found = 1;
    674             }
    675             else                                                                       // no matching : skip
    676             {
    677                 offset = offset + DIR_ENTRY_SIZE;
    678             }
    679         }
    680         else                                           // searched name is long
    681         {
    682             get_name_from_long( dir_entry, name_entry );
    683 
    684             unsigned shift = ((ord & 0xf) - 1) * 13;
    685             if ( _strncmp( (char*)(file_name + shift),
    686                            (char*)name_entry, 13 ) == 0 )
    687             {
    688                 if ( (ord & 0xf) == 1 )
    689                 {
    690                     offset = offset + DIR_ENTRY_SIZE;
    691                     _write_entry(offset + field, size, _fat.fat_cache, value);
    692                     found = 1;
    693                 }
    694                 offset = offset + DIR_ENTRY_SIZE;
    695                 continue;
    696             }
    697             else                                                                       // no matching : skip
    698             {
    699                 offset = offset + ((ord & 0xf) * DIR_ENTRY_SIZE) + DIR_ENTRY_SIZE;
    700             }
    701         }
    702     }
    703 
    704     // write block to FAT
    705     if ( _fat_ioc_access( use_irq,
    706                           0,                // write
    707                           lba,
    708                           (unsigned int)_fat.fat_cache,
    709                           1 ) )             // one sector
    710     {
    711         _printf("\n[FAT ERROR] in _update_entry() cannot write sector %x\n",
    712                 lba );
    713         return 1;
    714     }
     1046
     1047            // prepare next iteration
     1048            node = child;
     1049            level--;
     1050        }
     1051    } // end while
    7151052
    7161053    return 0;
    717 } // end _update_entry()
    718 
    719 
    720 //////////////////////////////////////////////////////////////////////////////////
    721 // This function update the FS_INFO block:
    722 // last cluster allocated and number of free cluster.
    723 // Return 0 in case of success, > 0 if failure.
    724 //////////////////////////////////////////////////////////////////////////////////
    725 static inline
    726 unsigned int _update_fs_info( unsigned int use_irq )
    727 {
    728     unsigned int lba = _fat.fs_info_lba;
    729 
    730 #if GIET_DEBUG_FAT
    731 if ( _get_proctime() > GIET_DEBUG_FAT )
    732 _printf("\n[DEBUG FAT] _update_fs_info()\n");
    733 #endif
    734 
    735     // update FAT cache in case of miss
    736     if ( lba != _fat.cache_lba )
    737     {
    738         if ( _fat_ioc_access( use_irq,
     1054}  // end _get_buffer_from_cache()
     1055
     1056
     1057
     1058
     1059/////////////////////////////////////
     1060static unsigned int _update_fs_info()
     1061{
     1062    // update buffer if miss
     1063    if ( _fat.fs_info_lba != _fat.block_buffer_lba )
     1064    {
     1065        if ( _fat_ioc_access( 1,                 // descheduling
    7391066                              1,                 // read
    740                               lba,
    741                               (unsigned int)_fat.fat_cache,
    742                               1 ) )              // one sector
     1067                              _fat.fs_info_lba,
     1068                              (unsigned int)_fat.block_buffer,
     1069                              1 ) )              // one block
    7431070        {
    7441071            _printf("\n[FAT_ERROR] in _update_fs_info() cannot read block\n");
    7451072            return 1;
    7461073        }
    747         _fat.cache_lba = lba;
    748     }
    749 
    750     _write_entry( FS_FREE_CLUSTER     , _fat.fat_cache, _fat.number_free_cluster );
    751     _write_entry( FS_FREE_CLUSTER_HINT, _fat.fat_cache, _fat.last_cluster_allocated );
     1074        _fat.block_buffer_lba = _fat.fs_info_lba;
     1075    }
     1076
     1077    // update FAT buffer
     1078    unsigned int* ptr;
     1079    ptr  = (unsigned int*)(_fat.block_buffer + get_offset(FS_FREE_CLUSTERS) );
     1080    *ptr = _fat.free_clusters_number;
     1081
     1082    ptr  = (unsigned int*)(_fat.block_buffer + get_offset(FS_FREE_CLUSTER_HINT) );
     1083    *ptr = _fat.first_free_cluster;
    7521084   
    7531085    // write bloc to FAT
    754     if ( _fat_ioc_access( use_irq,
     1086    if ( _fat_ioc_access( 1,                // descheduling
    7551087                          0,                // write
    756                           lba,
    757                           (unsigned int)_fat.fat_cache,
    758                           1 ) )             // one sector
     1088                          _fat.fs_info_lba,
     1089                          (unsigned int)_fat.block_buffer,
     1090                          1 ) )             // one block
    7591091    {
    7601092        _printf("\n[FAT_ERROR] in _update_fs_info() cannot write block\n");
     
    7621094    }
    7631095
     1096#if (GIET_DEBUG_FAT & 1)
     1097if ( _get_proctime() > GIET_DEBUG_FAT )
     1098_printf("\n[DEBUG FAT] _update_fs_info() : nb_free = %x / first_free = %x\n",
     1099        _fat.free_clusters_number , _fat.first_free_cluster );
     1100#endif
     1101
    7641102    return 0;
    7651103}  // end _update_fs_info()
    7661104
    767 //////////////////////////////////////////////////////////////////////////////////
    768 // This function update FAT, write a new value into cluster index.
    769 // Used by the function _fat_allocate to update the chaining of clusters.
    770 // Return 0 in case of success, > 0 if failure.
    771 //////////////////////////////////////////////////////////////////////////////////
    772 static inline
    773 unsigned int _update_fat( unsigned int use_irq,
    774                           unsigned int cluster,
    775                           unsigned int value  )
    776 {
    777     unsigned int lba = _fat.fat_lba + (cluster / 128);
     1105
     1106
     1107/////////////////////////////////////////////////////////////////
     1108static inline unsigned int _get_fat_entry( unsigned int  cluster,
     1109                                           unsigned int* value )
     1110{
     1111    // compute cluster_id & entry_id in FAT
     1112    // a FAT cluster is an array of 1024 unsigned int entries
     1113    unsigned int       cluster_id = cluster >> 10;       
     1114    unsigned int       entry_id   = cluster & 0x3FF;
     1115
     1116    // get pointer on the relevant cluster descriptor in FAT cache
     1117    fat_cache_desc_t*  pdesc;
     1118    unsigned int*      buffer;
     1119    if ( _get_buffer_from_cache( NULL,               // Fat-Cache
     1120                                 cluster_id,
     1121                                 &pdesc ) ) return 1;
     1122
     1123    // get value from FAT slot
     1124    buffer = (unsigned int*)pdesc->buffer;
     1125    *value = buffer[entry_id];
     1126
     1127    return 0;
     1128}  // end _get_fat_entry()
     1129
     1130
     1131
     1132////////////////////////////////////////////////////////////////
     1133static inline unsigned int _set_fat_entry( unsigned int cluster,
     1134                                           unsigned int value  )
     1135{
     1136    // compute cluster_id & entry_id in FAT
     1137    // a FAT cluster is an array of 1024 unsigned int entries
     1138    unsigned int cluster_id = cluster >> 10;
     1139    unsigned int entry_id   = cluster & 0x3FF;
     1140
     1141    // get pointer on the relevant cluster descriptor in FAT cache
     1142    fat_cache_desc_t*  pdesc;
     1143    unsigned int*      buffer;
     1144    if ( _get_buffer_from_cache( NULL,               // Fat-Cache
     1145                                 cluster_id,
     1146                                 &pdesc ) )  return 1;           
     1147
     1148    // set value into FAT slot
     1149    buffer           = (unsigned int*)pdesc->buffer;
     1150    buffer[entry_id] = value;
     1151    pdesc->dirty     = 1;
     1152
     1153    return 0;
     1154} // end _set_fat_entry()
     1155
     1156
     1157
     1158//////////////////////////////////////////////////////
     1159static void _allocate_one_buffer( fat_inode_t*  inode,
     1160                                  unsigned int  cluster_id,
     1161                                  unsigned int  cluster )
     1162{
     1163    // search the 64-tree cache from top to bottom
     1164    fat_cache_node_t*  node   = inode->cache;
     1165    unsigned int       level  = inode->levels;
     1166
     1167    while ( level )
     1168    {
     1169        // compute child index
     1170        unsigned int index = (cluster_id >> (6*(level-1))) & 0x3F;
     1171
     1172        if ( level == 1 )        // last level => children are cluster descriptors
     1173        {
     1174            fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index];
     1175            if ( pdesc != NULL )      // slot not empty!!!
     1176            {
     1177                _printf("\n[FAT ERROR] in allocate_one buffer() : slot not empty "
     1178                        "in File-Cache <%s> / cluster_id = %d\n", inode->name , cluster_id );
     1179                _exit();
     1180            }
     1181 
     1182            // allocate a cluster descriptor and a 4K buffer
     1183            pdesc = _malloc( sizeof(fat_cache_desc_t) );
     1184            unsigned char* buffer = _malloc( 4096 );
     1185
     1186#if (GIET_DEBUG_FAT & 1)
     1187if ( _get_proctime() > GIET_DEBUG_FAT )
     1188_printf("\n[DEBUG FAT] _allocate_one_buffer() : buffer allocated to <%s> for cluster_id %d\n",
     1189        inode->name, cluster_id );
     1190#endif
     1191
     1192            // update cache and pdesc
     1193            node->children[index] = pdesc;
     1194            pdesc->lba     = _cluster_to_lba( cluster );
     1195            pdesc->buffer  = buffer;
     1196            pdesc->dirty   = 1;
     1197
     1198            // prepare next iteration
     1199            level--;
     1200        }
     1201        else                      // not last level => children are 64-tree nodes
     1202        {
     1203            fat_cache_node_t* child = (fat_cache_node_t*)node->children[index];
     1204            if ( child == NULL )  // miss
     1205            {
     1206                // allocate a cache node if miss
     1207                child = (fat_cache_node_t*)_malloc( sizeof(fat_cache_node_t) );
     1208                node->children[index] = child;   
     1209            }
     1210
     1211            // prepare next iteration
     1212            node  = child;
     1213            level--;
     1214        }
     1215    } // end while
     1216} // end _allocate_one_buffer
     1217
     1218
     1219
     1220
     1221///////////////////////////////////////////////////////////////////
     1222static unsigned int _allocate_one_cluster( unsigned int*  cluster ) 
     1223{
     1224    unsigned int nb_free = _fat.free_clusters_number;
     1225    unsigned int free    = _fat.first_free_cluster;
     1226
     1227    // scan FAT to get next free cluster index
     1228    unsigned int current = free;
     1229    unsigned int found   = 0;
     1230    unsigned int max     = (_fat.data_sectors >> 3);
     1231    unsigned int value;
     1232    do
     1233    {
     1234        // increment current
     1235        current++;
     1236
     1237        // get FAT entry indexed by current
     1238        if ( _get_fat_entry( current , &value ) ) return 1;
     1239        // test if free
     1240        if ( value == FREE_CLUSTER ) found = 1;
     1241    }
     1242    while ( (current < max) && (found == 0) );
     1243       
     1244    // check found 
     1245    if ( found == 0 )
     1246    {
     1247        _printf("\n[FAT_ERROR] in _allocate_one_cluster() : unconsistent FAT state");
     1248        return 1;
     1249    }
     1250
     1251    // update allocated FAT slot
     1252    if ( _set_fat_entry( free , END_OF_CHAIN_CLUSTER_MAX ) ) return 1;
     1253
     1254    // update FAT descriptor global variables
     1255    _fat.free_clusters_number = nb_free - 1;
     1256    _fat.first_free_cluster   = current;
     1257
     1258#if (GIET_DEBUG_FAT & 1)
     1259if ( _get_proctime() > GIET_DEBUG_FAT )
     1260_printf("\n[DEBUG FAT] _allocate_one_cluster() : cluster = %x / first_free = %x\n",
     1261        free , current );
     1262#endif
     1263
     1264    // returns free cluster index
     1265    *cluster = free;
     1266    return 0;
     1267
     1268}  // end _allocate_one_cluster()
     1269
     1270
     1271
     1272
     1273//////////////////////////////////////////////////////////////////////////
     1274static unsigned int _update_device_from_cache( unsigned int        levels,
     1275                                               fat_cache_node_t*   root,
     1276                                               char*               string )
     1277{
     1278    unsigned int index;
     1279    unsigned int ret = 0;
     1280
     1281    if ( levels == 1 )  // last level => children are cluster descriptors
     1282    {
     1283        for( index = 0 ; index < 64 ; index++ )
     1284        {
     1285            fat_cache_desc_t* pdesc = root->children[index];
     1286            if ( pdesc != NULL )
     1287            {
     1288                // update cluster on device if dirty
     1289                if ( pdesc->dirty )
     1290                {
     1291                    if ( _fat_ioc_access( 1,           // descheduling
     1292                                          0,           // to block device
     1293                                          pdesc->lba,
     1294                                          (unsigned int)pdesc->buffer,
     1295                                          8 ) )
     1296                    {
     1297                        _printf("\n[FAT_ERROR] in _update_device from_cache() : "
     1298                                " cannot access lba = %x\n", pdesc->lba );
     1299                        ret = 1;
     1300                    }
     1301                    else
     1302                    {
     1303                        pdesc->dirty = 0;
     1304
     1305#if (GIET_DEBUG_FAT & 1)
     1306if ( _get_proctime() > GIET_DEBUG_FAT )
     1307_printf("\n[DEBUG FAT] _update_device_from_cache() : cluster_id = %d for <%s>\n",
     1308        index , string );
     1309#endif
     1310
     1311                    }
     1312                }
     1313            }
     1314        }
     1315    }
     1316    else               // not the last level = recursive call on each children
     1317    {
     1318        for( index = 0 ; index < 64 ; index++ )
     1319        {
     1320            fat_cache_node_t* pnode = root->children[index];
     1321            if ( pnode != NULL )
     1322            {
     1323                if ( _update_device_from_cache( levels - 1,
     1324                                                root->children[index],
     1325                                                string ) ) ret = 1;
     1326            }   
     1327        }
     1328    }
     1329    return ret;
     1330}  // end _update_device_from_cache()
     1331
     1332
     1333
     1334///////////////////////////////////////////////////////////////////
     1335static unsigned int _release_cache_memory( fat_cache_node_t*  root,
     1336                                           unsigned int       levels )
     1337{
     1338    unsigned int index;
     1339    unsigned int ret = 0;
     1340
     1341    if ( levels == 1 )  // last level => children are cluster descriptors
     1342    {
     1343        for( index = 0 ; index < 64 ; index++ )
     1344        {
     1345            fat_cache_desc_t* pdesc = root->children[index];
     1346
     1347            if ( pdesc != NULL )
     1348            {
     1349                // check dirty
     1350                if ( pdesc->dirty )
     1351                {
     1352                    _printf("\n[FAT_ERROR] in _release_cache_memory() : dirty cluster\n");
     1353                    ret = 1;
     1354                }
     1355                else
     1356                {
     1357                    _free( pdesc->buffer );
     1358                    _free( pdesc );
     1359                    root->children[index] = NULL;
     1360                }
     1361            }
     1362        }
     1363    }
     1364    else               // not the last level = recursive call on each children
     1365    {
     1366        for( index = 0 ; index < 64 ; index++ )
     1367        {
     1368            fat_cache_node_t*    cnode = root->children[index];
     1369
     1370            if ( cnode != NULL ) ret   = _release_cache_memory( root->children[index],
     1371                                                                levels - 1 );
     1372        }
     1373    }
     1374    return ret;
     1375}  // end _release_cache_memory()
     1376
     1377
     1378
     1379
     1380
     1381/////////////////////////////////////////////////////////////
     1382static unsigned int _clusters_allocate( fat_inode_t* inode,
     1383                                        unsigned int nb_current_clusters,
     1384                                        unsigned int nb_required_clusters )
     1385{
     1386    // Check if FAT contains enough free clusters
     1387    if ( nb_required_clusters > _fat.free_clusters_number )
     1388    {
     1389        _printf("\n[FAT ERROR] in _clusters_allocate() : required_clusters = %d"
     1390                " / free_clusters = %d\n", nb_required_clusters , _fat.free_clusters_number );
     1391        return 1;
     1392    }
     1393
     1394#if (GIET_DEBUG_FAT & 1)
     1395if ( _get_proctime() > GIET_DEBUG_FAT )
     1396_printf("\n[DEBUG FAT] _clusters_allocate() : enters for <%s> / nb_current_clusters = %d "
     1397        "/ nb_required_clusters = %d\n",
     1398        inode->name , nb_current_clusters , nb_required_clusters );
     1399#endif
     1400 
     1401    // compute last allocated cluster index when (nb_current_clusters > 0)
     1402    unsigned int current = inode->cluster;
     1403    unsigned int next;
     1404    unsigned int last;
     1405    if ( nb_current_clusters )   // clusters allocated => search last
     1406    {   
     1407        while ( current < END_OF_CHAIN_CLUSTER_MIN )
     1408        {
     1409            // get next cluster
     1410            if ( _get_fat_entry( current , &next ) )  return 1;
     1411            last    = current;
     1412            current = next;
     1413        }
     1414    } 
     1415
     1416    // Loop on the new clusters to be allocated
     1417    // if (nb_current_clusters == 0) the first new cluster index must
     1418    //                               be written in inode->cluster field
     1419    // if (nb_current_clusters >  0) the first new cluster index must
     1420    //                               be written in FAT[last]
     1421    unsigned int      cluster_id;
     1422    unsigned int      new;
     1423    for ( cluster_id = nb_current_clusters ;
     1424          cluster_id < (nb_current_clusters + nb_required_clusters) ;
     1425          cluster_id ++ )
     1426    {
     1427        // allocate one cluster on block device
     1428        if ( _allocate_one_cluster( &new ) ) return 1;
     1429
     1430        // allocate one 4K buffer to File-Cache
     1431        _allocate_one_buffer( inode,
     1432                              cluster_id,
     1433                              new );
     1434
     1435        if ( cluster_id == 0 )  // update inode
     1436        {
     1437            inode->cluster = new;
     1438        }
     1439        else                    // update FAT
     1440        {
     1441            if ( _set_fat_entry( last , new ) ) return 1;
     1442        }
     1443
     1444#if (GIET_DEBUG_FAT & 1)
     1445if ( _get_proctime() > GIET_DEBUG_FAT )
     1446_printf("\n[DEBUG FAT] _clusters_allocate() : done for cluster_id = %d / cluster = %x\n",
     1447        cluster_id , new );
     1448#endif
     1449
     1450        // update loop variables
     1451        last = new;
     1452
     1453    } // end for loop
     1454
     1455    // update FAT : last slot should contain END_OF_CHAIN_CLUSTER_MAX
     1456    if ( _set_fat_entry( last , END_OF_CHAIN_CLUSTER_MAX ) )  return 1;
     1457
     1458    // update the FAT on block device
     1459    if ( _update_device_from_cache( _fat.fat_cache_levels,
     1460                                    _fat.fat_cache_root,
     1461                                    "FAT" ) )              return 1;
     1462    return 0;
     1463}  // end _clusters_allocate()
     1464
     1465
     1466
     1467//////////////////////////////////////////////////////////////
     1468static unsigned int _clusters_release( unsigned int cluster )
     1469{
     1470    // scan the FAT
     1471    unsigned int current = cluster;
     1472    unsigned int next;
     1473    do
     1474    {
     1475        // get next_cluster index
     1476        if ( _get_fat_entry( current , &next ) )  return 1;
     1477
     1478        // release current_cluster
     1479        if ( _set_fat_entry( current , FREE_CLUSTER ) )   return 1;
     1480
     1481        // update first_free_cluster and free_clusters_number in FAT descriptor
     1482        _fat.free_clusters_number = _fat.free_clusters_number + 1;
     1483        if ( _fat.first_free_cluster > current ) _fat.first_free_cluster = current;
     1484
     1485        // update loop variable
     1486        current = next;
     1487    }
     1488    while ( next < END_OF_CHAIN_CLUSTER_MIN );
     1489
     1490    // update the FAT on block device
     1491    if ( _update_device_from_cache( _fat.fat_cache_levels,
     1492                                    _fat.fat_cache_root,
     1493                                    "FAT" ) )                return 1;
     1494    return 0;
     1495}  // end _clusters_release()
     1496
     1497
     1498
     1499///////////////////////////////////////////////////////////
     1500static void _add_special_directories( fat_inode_t*  child,
     1501                                      fat_inode_t*  parent )
     1502{
     1503    // get first File-Cache buffer for child
     1504    fat_cache_desc_t*   pdesc  = (fat_cache_desc_t*)child->cache->children[0];
     1505    unsigned char*      entry;
     1506
     1507    unsigned int i;
     1508    unsigned int cluster;
     1509    unsigned int size;
     1510
     1511    // set "." entry (32 bytes)
     1512    cluster = child->cluster;
     1513    size    = child->size;
     1514    entry   = pdesc->buffer;
     1515   
     1516    for ( i = 0 ; i < 32 ; i++ )
     1517    {
     1518        if      (i == 0 )     entry[i] = 0x2E;          // SFN
     1519        else if (i <  11)     entry[i] = 0x20;          // SFN
     1520        else if (i == 11)     entry[i] = 0x10;          // ATTR == dir
     1521        else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2
     1522        else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3
     1523        else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0
     1524        else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1
     1525        else if (i == 28)     entry[i] = size>>0;       // size.B0
     1526        else if (i == 29)     entry[i] = size>>8;       // size.B1
     1527        else if (i == 30)     entry[i] = size>>16;      // size.B2
     1528        else if (i == 31)     entry[i] = size>>24;      // size.B3
     1529        else                  entry[i] = 0x00;
     1530    }
     1531
     1532    // set ".." entry (32 bytes)
     1533    cluster = parent->cluster;
     1534    size    = parent->size;
     1535    entry   = pdesc->buffer + 32;
     1536
     1537    for ( i = 0 ; i < 32 ; i++ )
     1538    {
     1539        if      (i <  2 )     entry[i] = 0x2E;          // SFN
     1540        else if (i <  11)     entry[i] = 0x20;          // SFN
     1541        else if (i == 11)     entry[i] = 0x10;          // ATTR == dir
     1542        else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2
     1543        else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3
     1544        else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0
     1545        else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1
     1546        else if (i == 28)     entry[i] = size>>0;       // size.B0
     1547        else if (i == 29)     entry[i] = size>>8;       // size.B1
     1548        else if (i == 30)     entry[i] = size>>16;      // size.B2
     1549        else if (i == 31)     entry[i] = size>>24;      // size.B3
     1550        else                  entry[i] = 0x00;
     1551    }
     1552}  // end _add_special_directories
     1553
     1554
     1555
     1556////////////////////////////////////////////////////////////
     1557static unsigned int _check_name_length( char* name,
     1558                                        unsigned int* length,
     1559                                        unsigned int* nb_lfn )
     1560{
     1561    unsigned int len = _strlen( name );
     1562    if      ( len <= 13 )
     1563    {
     1564        *length  = len;
     1565        *nb_lfn  = 1;
     1566        return 0;
     1567    }
     1568    else if ( len <= 26 )
     1569    {
     1570        *length  = len;
     1571        *nb_lfn  = 2;
     1572        return 0;
     1573    }
     1574    else if ( len <= 31 )
     1575    {
     1576        *length  = len;
     1577        *nb_lfn  = 3;
     1578        return 0;
     1579    }
     1580    else
     1581    {
     1582        return 1;
     1583    }
     1584}  // _check_name_length()
     1585
     1586
     1587
     1588
     1589///////////////////////////////////////////////////////////
     1590static unsigned int _get_nb_entries( fat_inode_t*   inode,
     1591                                     unsigned int*  nb_entries )
     1592{
     1593    // scan directory until "end of directory" with two embedded loops:
     1594    // - scan the clusters allocated to this directory
     1595    // - scan the entries to find NO_MORE_ENTRY
     1596    fat_cache_desc_t*  pdesc;                      // pointer on buffer descriptor
     1597    unsigned char*     buffer;                     // 4 Kbytes buffer (one cluster)
     1598    unsigned int       ord;                        // ORD field in directory entry
     1599    unsigned int       attr;                       // ATTR field in directory entry
     1600    unsigned int       cluster_id = 0;             // cluster index in directory
     1601    unsigned int       offset     = 0;             // position in scanned buffer
     1602    unsigned int       found      = 0;             // NO_MORE_ENTRY found
     1603    unsigned int       count      = 0;             // number of valid NORMAL entries
     1604
     1605    // loop on clusters allocated to directory
     1606    while ( found == 0 )
     1607    {
     1608        // get one 4 Kytes buffer from File_Cache 
     1609        if ( _get_buffer_from_cache( inode,
     1610                                     cluster_id,
     1611                                     &pdesc ) )   return 1;
     1612
     1613        buffer = pdesc->buffer;
     1614       
     1615        // loop on directory entries in buffer
     1616        while ( (offset < 4096) && (found == 0) )
     1617        {
     1618            attr = _read_entry( DIR_ATTR , buffer + offset , 0 );   
     1619            ord  = _read_entry( LDIR_ORD , buffer + offset , 0 );
     1620
     1621            if ( ord == NO_MORE_ENTRY )
     1622            {
     1623                found = 1;
     1624            } 
     1625            else if ( ord == FREE_ENTRY )             // free entry => skip
     1626            {
     1627                offset = offset + 32;
     1628            }
     1629            else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => skip
     1630            {
     1631                offset = offset + 32;
     1632            }
     1633            else                                      // NORMAL entry
     1634            {
     1635                count++;
     1636            }
     1637
     1638            offset = offset + 32;
     1639
     1640        }  // end loop on directory entries
     1641
     1642        cluster_id++;
     1643        offset = 0;
     1644
     1645    }  // end loop on clusters
     1646
     1647    // return nb_entries
     1648    *nb_entries = count;
     1649   
     1650    return 0;
     1651}  // end dir_not_empty()
     1652
     1653
     1654
     1655///////////////////////////////////////////////////////////
     1656static unsigned int _add_dir_entry( fat_inode_t*   child,
     1657                                    fat_inode_t*   parent )
     1658{
     1659    // get child attributes
     1660    unsigned int      is_dir  = child->is_dir;     
     1661    unsigned int      size    = child->size;
     1662    unsigned int      cluster = child->cluster;
     1663
     1664    // compute number of required entries to store child->name
     1665    // - Short name (less than 13 characters) require 3 entries:
     1666    //   one LFN entry / one NORMAL entry / one NO_MORE_ENTRY entry.
     1667    // - Longer names (up to 31 characters) can require 4 or 5 entries:
     1668    //   2 or 3 LFN entries / one NORMAL entry / one NO_MORE entry.
     1669    unsigned int length;
     1670    unsigned int nb_lfn;
     1671    if ( _check_name_length( child->name,
     1672                             &length,
     1673                             &nb_lfn ) )  return 1;
     1674
     1675#if (GIET_DEBUG_FAT & 1)
     1676if ( _get_proctime() > GIET_DEBUG_FAT )
     1677_printf("\n[DEBUG FAT] _add_dir_entry() : try to add <%s> in <%s> / nb_lfn = %d\n",
     1678        child->name , parent->name, nb_lfn );
     1679#endif
     1680
     1681    // Find end of directory : two embedded loops:
     1682    // - scan the clusters allocated to this directory
     1683    // - scan the entries to find NO_MORE_ENTRY
     1684    fat_cache_desc_t*  pdesc;                      // pointer on buffer descriptor
     1685    unsigned char*     buffer;                     // 4 Kbytes buffer (one cluster)
     1686    unsigned int       cluster_id = 0;             // cluster index in directory
     1687    unsigned int       offset     = 0;             // position in scanned buffer
     1688    unsigned int       found      = 0;             // NO_MORE_ENTRY found
     1689
     1690    // loop on clusters allocated to directory
     1691    while ( found == 0 )
     1692    {
     1693        // get one 4 Kytes buffer from File_Cache 
     1694        if ( _get_buffer_from_cache( parent,
     1695                                     cluster_id,
     1696                                     &pdesc ) )   return 1;
     1697
     1698        buffer = pdesc->buffer;
     1699       
     1700        // loop on directory entries in buffer
     1701        while ( (offset < 4096) && (found == 0) )
     1702        {
     1703            if ( _read_entry( LDIR_ORD , buffer + offset , 0 ) == NO_MORE_ENTRY )
     1704            {
     1705                found        = 1;
     1706                pdesc->dirty = 1;
     1707            } 
     1708            else
     1709            {
     1710                offset = offset + 32;
     1711            }
     1712        }  // end loop on entries
     1713        if ( found == 0 )
     1714        {
     1715            cluster_id++;
     1716            offset = 0;
     1717        }
     1718    }  // end loop on clusters
     1719
     1720#if (GIET_DEBUG_FAT & 1)
     1721if ( _get_proctime() > GIET_DEBUG_FAT )
     1722_printf("\n[DEBUG FAT] _add_dir_entry() : get NO_MORE directory entry : "
     1723        " buffer = %x / offset = %x / cluster_id = %d\n",
     1724        (unsigned int)buffer , offset , cluster_id );
     1725#endif
     1726
     1727    // enter FSM :
     1728    // The new child requires to write 3, 4, or 5 directory entries.
     1729    // To actually register the new child, we use a 5 steps FSM
     1730    // (one state per entry to be written), that is traversed as:
     1731    //    LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE
     1732    // The buffer and first directory entry to be  written are identified
     1733    // by the variables : buffer / cluster_id / offset
     1734
     1735    unsigned char* name  = (unsigned char*)child->name;
     1736
     1737    unsigned int step;          // FSM state
     1738
     1739    if      ( nb_lfn == 1 ) step = 3;
     1740    else if ( nb_lfn == 2 ) step = 4;
     1741    else if ( nb_lfn == 3 ) step = 5;
     1742   
     1743    unsigned int   i;           // byte index in 32 bytes directory
     1744    unsigned int   c;           // character index in name
     1745    unsigned char* entry;       // buffer + offset;
     1746
     1747    while ( step )   
     1748    {
     1749        // get another buffer if required
     1750        if ( offset >= 4096 )  // new buffer required
     1751        {
     1752            if ( cluster_id == 63 )   // we need to increase depth of File-Cache
     1753            {
     1754                _printf("\n[FAT ERROR] in add_dir_entry() File Cache depth extension "
     1755                        " not implemented\n" );
     1756                _exit();  // TODO   
     1757            }
     1758            else
     1759            {
     1760                if ( _get_buffer_from_cache( parent,
     1761                                             cluster_id + 1,
     1762                                             &pdesc ) )      return 1;       
     1763                buffer       = pdesc->buffer;
     1764                pdesc->dirty = 1;
     1765                offset       = 0;
     1766            }
     1767        }
     1768
     1769        // compute directory entry address
     1770        entry = buffer + offset;
     1771
     1772#if (GIET_DEBUG_FAT & 1)
     1773if ( _get_proctime() > GIET_DEBUG_FAT )
     1774_printf("\n[DEBUG FAT] _add_dir_entry() : FSM step = %d /"
     1775        " offset = %x / nb_lfn = %d\n", step, offset, nb_lfn );
     1776#endif
     1777
     1778        // write one 32 bytes directory entry per iteration
     1779        switch ( step )
     1780        {
     1781            case 5:   // write LFN3 entry
     1782            {
     1783                c = 26;
     1784                // scan the 32 bytes in dir_entry
     1785                for ( i = 0 ; i < 32 ; i++ )
     1786                {
     1787                    if (i == 0)
     1788                    {
     1789                        if ( nb_lfn == 3) entry[i] = 0x43;
     1790                        else              entry[i] = 0x03;
     1791                    }
     1792                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1793                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1794                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1795                              ( c < length ) )
     1796                    {
     1797                                          entry[i] = name[c];
     1798                                          c++;
     1799                    }
     1800                    else if (i == 11)     entry[i] = 0x0F;
     1801                    else if (i == 12)     entry[i] = 0xCA;
     1802                    else                  entry[i] = 0x00;
     1803                }
     1804                step--;
     1805                break;
     1806            }
     1807            case 4:   // write LFN2 entry 
     1808            {
     1809                c = 13;
     1810                // scan the 32 bytes in dir_entry
     1811                for ( i = 0 ; i < 32 ; i++ )
     1812                {
     1813                    if (i == 0)
     1814                    {
     1815                        if ( nb_lfn == 2) entry[i] = 0x42;
     1816                        else              entry[i] = 0x02;
     1817                    }
     1818                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1819                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1820                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1821                              ( c < length ) )
     1822                    {
     1823                                          entry[i] = name[c];
     1824                                          c++;
     1825                    }
     1826                    else if (i == 11)     entry[i] = 0x0F;
     1827                    else if (i == 12)     entry[i] = 0xCA;
     1828                    else                  entry[i] = 0x00;
     1829                }
     1830                step--;
     1831                break;
     1832            }
     1833            case 3:   // Write LFN1 entry   
     1834            {
     1835                c = 0;
     1836                // scan the 32 bytes in dir_entry
     1837                for ( i = 0 ; i < 32 ; i++ )
     1838                {
     1839                    if (i == 0)
     1840                    {
     1841                        if ( nb_lfn == 1) entry[i] = 0x41;
     1842                        else              entry[i] = 0x01;
     1843                    }
     1844                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1845                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1846                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1847                              ( c < length ) )
     1848                    {
     1849                                          entry[i] = name[c];
     1850                                          c++;
     1851                    }
     1852                    else if (i == 11)     entry[i] = 0x0F;
     1853                    else if (i == 12)     entry[i] = 0xCA;
     1854                    else                  entry[i] = 0x00;
     1855                }
     1856                step--;
     1857                break;
     1858            }
     1859            case 2:   // write NORMAL entry     
     1860            {
     1861                c = 0;
     1862                // scan the 32 bytes in dir_entry
     1863                for ( i = 0 ; i < 32 ; i++ )
     1864                {
     1865                    if      ( (i < 8) && (c < length) )             // SFN
     1866                    {
     1867                                          entry[i] = _to_upper( name[c] );
     1868                                          c++;
     1869                    }
     1870                    else if (i <  11)     entry[i] = 0x20;          // EXT
     1871                    else if (i == 11)                               // ATTR
     1872                    {
     1873                        if (is_dir)       entry[i] = 0x10;
     1874                        else              entry[i] = 0x20;
     1875                    }
     1876                    else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2
     1877                    else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3
     1878                    else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0
     1879                    else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1
     1880                    else if (i == 28)     entry[i] = size>>0;       // size.B0
     1881                    else if (i == 29)     entry[i] = size>>8;       // size.B1
     1882                    else if (i == 30)     entry[i] = size>>16;      // size.B2
     1883                    else if (i == 31)     entry[i] = size>>24;      // size.B3
     1884                    else                  entry[i] = 0x00;
     1885                }
     1886
     1887                // update the dentry field in child inode
     1888                child->dentry = ((cluster_id<<12) + offset)>>5;
     1889
     1890                step--;
     1891                break;
     1892            }
     1893            case 1:   // write NOMORE entry 
     1894            {
     1895                step--;
     1896                entry [0] = 0x00;
     1897                break;
     1898            }
     1899        } // end switch step
     1900        offset += 32;
     1901    } // exit while => exit FSM   
     1902
     1903#if (GIET_DEBUG_FAT & 1)
     1904if ( _get_proctime() > GIET_DEBUG_FAT )
     1905{
     1906    _printf("\n[DEBUG FAT] _add_dir_entry() : <%s> successfully added in <%s>\n",
     1907            child->name , parent->name );
     1908}
     1909#endif
     1910
     1911    return 0;       
     1912} // end _add_dir_entry
     1913
     1914
     1915
     1916////////////////////////////////////////////////////////////
     1917static unsigned int _remove_dir_entry( fat_inode_t*  inode )
     1918{
     1919    // compute number of LFN entries
     1920    unsigned int length;
     1921    unsigned int nb_lfn;
     1922    if ( _check_name_length( inode->name,
     1923                             &length,
     1924                             &nb_lfn ) )  return 1;
     1925
     1926    // get cluster_id and offset in parent directory cache
     1927    unsigned int  dentry     = inode->dentry;
     1928    unsigned int  cluster_id = dentry >> 7;
     1929    unsigned int  offset     = (dentry & 0x7F)<<5;
     1930
     1931    // get buffer from parent directory cache
     1932    unsigned char*     buffer;
     1933    fat_cache_desc_t*  pdesc;
     1934
     1935    if ( _get_buffer_from_cache( inode->parent,
     1936                                 cluster_id,
     1937                                 &pdesc ) ) return 1;
     1938    buffer       = pdesc->buffer;
     1939    pdesc->dirty = 1;
     1940
     1941    // invalidate NORMAL entry in directory cache
     1942    buffer[offset] = 0xE5;
     1943
     1944    // invalidate LFN entries
     1945    while ( nb_lfn )
     1946    {
     1947        if (offset == 0)  // me must load buffer for (cluster_id - 1)
     1948        {
     1949            if ( _get_buffer_from_cache( inode->parent,
     1950                                         cluster_id - 1,
     1951                                         &pdesc ) )   return 1;
     1952            buffer       = pdesc->buffer;
     1953            pdesc->dirty = 1;
     1954            offset       = 4064;
     1955        }
     1956        else
     1957        {
     1958            offset = offset - 32;
     1959        }
     1960
     1961        // invalidate LFN entry
     1962        buffer[offset] = 0xE5;
     1963
     1964        nb_lfn--;
     1965    }     
     1966         
     1967    return 0;
     1968}  // end _remove_dir_entry
     1969
     1970
     1971
     1972
     1973////////////////////////////////////////////////////////////
     1974static unsigned int _update_dir_entry( fat_inode_t*  inode )
     1975
     1976    // get Cache-File buffer containing the parent directory entry
     1977    // 128 directories entries in one 4 Kbytes buffer
     1978    fat_cache_desc_t*  pdesc;
     1979    unsigned char*     buffer;   
     1980    unsigned int       cluster_id = inode->dentry>>7;
     1981    unsigned int       offset     = (inode->dentry & 0x3F)<<5;
     1982
     1983    if ( _get_buffer_from_cache( inode->parent,
     1984                                 cluster_id,
     1985                                 &pdesc ) )    return 1;
     1986    buffer       = pdesc->buffer;
     1987    pdesc->dirty = 1;
     1988
     1989    // update size field
     1990    buffer[offset + 28] = inode->size>>0;       // size.B0
     1991    buffer[offset + 29] = inode->size>>8;       // size.B1
     1992    buffer[offset + 30] = inode->size>>16;      // size.B2
     1993    buffer[offset + 31] = inode->size>>24;      // size.B3
     1994
     1995    // update cluster field
     1996    buffer[offset + 26] = inode->cluster>>0;    // cluster.B0
     1997    buffer[offset + 27] = inode->cluster>>8;    // cluster.B1
     1998    buffer[offset + 20] = inode->cluster>>16;   // cluster.B2
     1999    buffer[offset + 21] = inode->cluster>>24;   // cluster.B3
     2000   
     2001    return 0;
     2002} // end _update_dir_entry()
     2003
     2004
     2005
     2006
     2007//////////////////////////////////////////////////////////////////
     2008static unsigned int _get_child_from_parent( fat_inode_t*   parent,
     2009                                            char*          name,
     2010                                            fat_inode_t**  inode )
     2011{
     2012    fat_inode_t*   current;
     2013
     2014#if (GIET_DEBUG_FAT & 1)
     2015if ( _get_proctime() > GIET_DEBUG_FAT )
     2016_printf("\n[DEBUG FAT] _get_child_from_parent() : search <%s> in directory <%s>\n",
     2017        name , parent->name );
     2018#endif
     2019
     2020    // compute name lenth
     2021    unsigned int length = _strlen( name );
     2022   
     2023    // scan inodes in the parent directory
     2024    for ( current = parent->child ; current ; current = current->next )
     2025    {
     2026        if ( _strncmp( name , current->name , length ) == 0 )
     2027        {
     2028
     2029#if (GIET_DEBUG_FAT & 1)
     2030if ( _get_proctime() > GIET_DEBUG_FAT )
     2031_printf("\n[DEBUG FAT] _get_child_from_parent() : found inode <%s> in directory <%s>\n",
     2032        name , parent->name );
     2033#endif
     2034            *inode = current;
     2035            return 0;           // name found
     2036        }
     2037    }
     2038
     2039    // not found in Inode-Tree => access the parent directory
     2040    // file_cache.  Two embedded loops:
     2041    // - scan the clusters allocated to this directory
     2042    // - scan the directory entries in each 4 Kbytes buffer
     2043
     2044    unsigned char*    buffer;           // pointer on one cache buffer
     2045    char              cname[32];        // buffer for one full entry name
     2046    char              lfn1[16];         // buffer for one partial name
     2047    char              lfn2[16];         // buffer for one partial name
     2048    char              lfn3[16];         // buffer for one partial name
     2049    unsigned int      size;             // searched file/dir size (bytes)
     2050    unsigned int      cluster;          // searched file/dir cluster index
     2051    unsigned int      is_dir;           // searched file/dir type
     2052    unsigned int      attr;             // directory entry ATTR field
     2053    unsigned int      ord;              // directory entry ORD field
     2054    unsigned int      lfn;              // LFN entries number             
     2055    unsigned int      dentry;           // directory entry index
     2056    unsigned int      offset     = 0;   // byte offset in buffer
     2057    unsigned int      cluster_id = 0;   // cluster index in directory
     2058    int               found      = 0;   // not found (0) / name found (1) / end of dir (-1)
     2059
     2060#if (GIET_DEBUG_FAT & 1)
     2061if ( _get_proctime() > GIET_DEBUG_FAT )
     2062_printf("\n[DEBUG FAT] _get_child_from_parent() : does not found inode <%s>"
     2063        " in directory <%s> => search in cache\n", name , parent->name );
     2064#endif
     2065
     2066    // scan the clusters allocated to parent directory
     2067    while ( found == 0 )
     2068    {
     2069        // get one 4 Kytes buffer from parent File_Cache 
     2070        fat_cache_desc_t*  pdesc;
     2071        if ( _get_buffer_from_cache( parent,
     2072                                     cluster_id,
     2073                                     &pdesc ) )    return 2;
     2074        buffer = pdesc->buffer;
     2075
     2076        // scan this buffer until end of directory, end of buffer, or name found
     2077        while( (offset < 4096) && (found == 0) )
     2078        {
     2079
     2080#if (GIET_DEBUG_FAT & 1)
     2081if ( _get_proctime() > GIET_DEBUG_FAT )
     2082_printf("\n[DEBUG FAT] _get_child_from_parent() : scan buffer %d for <%s>\n",
     2083        cluster_id , name );
     2084#endif
     2085            attr = _read_entry( DIR_ATTR , buffer + offset , 0 );   
     2086            ord  = _read_entry( LDIR_ORD , buffer + offset , 0 );
     2087
     2088            if (ord == NO_MORE_ENTRY)                 // no more entry in directory => break
     2089            {
     2090                found = -1;
     2091            }
     2092            else if ( ord == FREE_ENTRY )             // free entry => skip
     2093            {
     2094                offset = offset + 32;
     2095            }
     2096            else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => get partial name
     2097            {
     2098                unsigned int seq = ord & 0x3;
     2099                lfn = (seq > lfn) ? seq : lfn;   
     2100                if      ( seq == 1 ) _get_name_from_long( buffer + offset, lfn1 );
     2101                else if ( seq == 2 ) _get_name_from_long( buffer + offset, lfn2 );
     2102                else if ( seq == 3 ) _get_name_from_long( buffer + offset, lfn3 );
     2103                offset = offset + 32;
     2104            }
     2105            else                                 // NORMAL entry
     2106            {
     2107                // build the extracted name
     2108                if      ( lfn == 0 )
     2109                {
     2110                    _get_name_from_short( buffer + offset , cname );
     2111                }
     2112                else if ( lfn == 1 )
     2113                {
     2114                    _strcpy( cname      , lfn1 );
     2115                }   
     2116                else if ( lfn == 2 )
     2117                {
     2118                    _strcpy( cname      , lfn1 );
     2119                    _strcpy( cname + 13 , lfn2 );
     2120                }
     2121                else if ( lfn == 3 )
     2122                {
     2123                    _strcpy( cname      , lfn1 );
     2124                    _strcpy( cname + 13 , lfn2 );
     2125                    _strcpy( cname + 26 , lfn3 );
     2126                }
     2127                   
     2128                // test if extracted name == searched name
     2129                if ( _strncmp( name , cname , length ) == 0 )
     2130                {
     2131                    cluster = (_read_entry( DIR_FST_CLUS_HI , buffer + offset , 1 ) << 16) |
     2132                              (_read_entry( DIR_FST_CLUS_LO , buffer + offset , 1 )      ) ;
     2133                    dentry  = ((cluster_id<<12) + offset)>>5;
     2134                    is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     2135                    size    = _read_entry( DIR_FILE_SIZE , buffer + offset , 1 );
     2136                    found   = 1;
     2137                }
     2138                offset = offset + 32;
     2139                lfn    = 0;
     2140            }
     2141        }  // end loop on directory entries
     2142        cluster_id++;
     2143        offset = 0;
     2144    }  // end loop on buffers
     2145
     2146    if ( found == -1 )  // found end of directory in parent directory
     2147    {
     2148
     2149#if (GIET_DEBUG_FAT & 1)
     2150if ( _get_proctime() > GIET_DEBUG_FAT )
     2151_printf("\n[DEBUG FAT] _get_child_from_parent() : found end of directory in <%s>\n",
     2152        parent->name );
     2153#endif
     2154        *inode = NULL;
     2155        return 1;
     2156    }
     2157    else               // found searched name in parent directory
     2158    {
     2159        // allocate a new inode and an empty Cache-File
     2160        *inode = _allocate_one_inode( name,
     2161                                      is_dir,
     2162                                      cluster,
     2163                                      size,
     2164                                      0,             // count
     2165                                      dentry,
     2166                                      1 );           // cache_allocate
     2167
     2168        // introduce it in Inode-Tree
     2169        _add_inode_in_tree( *inode , parent );
     2170
     2171#if (GIET_DEBUG_FAT & 1)
     2172if ( _get_proctime() > GIET_DEBUG_FAT )
     2173_printf("\n[DEBUG FAT] _get_child_from_parent() : found <%s> on device\n", name );
     2174#endif
     2175        return 0;
     2176    }
     2177}  // end _get_child_from_parent()
     2178
     2179
     2180
     2181
     2182//////////////////////////////////////////////////////////////////
     2183static unsigned int _get_inode_from_path( char*          pathname,
     2184                                          fat_inode_t**  inode )
     2185{
     2186    char                 name[32];         // buffer for one name in pathname
     2187    unsigned int         nb_read;              // number of characters written in name[]
     2188    fat_inode_t*         parent;           // parent inode
     2189    fat_inode_t*         child;            // child inode
     2190    unsigned int         last;             // while exit condition
     2191    unsigned int         code;             // return value
     2192
     2193#if (GIET_DEBUG_FAT & 1)
     2194if ( _get_proctime() > GIET_DEBUG_FAT )
     2195_printf("\n[DEBUG FAT] _get_inode_from_path() : enters for path <%s>\n", pathname );
     2196#endif
     2197
     2198    // handle root directory case
     2199    if ( _strncmp( pathname , "/" , 2 ) == 0 )
     2200    {
     2201
     2202#if (GIET_DEBUG_FAT & 1)
     2203if ( _get_proctime() > GIET_DEBUG_FAT )
     2204_printf("\n[DEBUG FAT] _get_inode_from_path() : found root inode for <%s>\n",
     2205        pathname );
     2206#endif
     2207        *inode  = _fat.inode_tree_root;
     2208        return 0;
     2209    }
     2210
     2211    // If the pathname is not "/", we traverse the inode tree from the root.
     2212    // We use _get_name_from_path() to scan pathname and extract inode names.
     2213    // We use _get_child_from_parent() to scan each directory in the path.
     2214
     2215    last       = 0;
     2216    nb_read    = 0;                      // number of characters analysed in path
     2217    parent     = _fat.inode_tree_root;   // Inode-Tree root
     2218   
     2219    while ( last == 0 )
     2220    {
     2221        // get searched file/dir name
     2222        if ( _get_name_from_path( pathname, name, &nb_read ) )
     2223        {
     2224            return 3;   // error : name too long
     2225        }
     2226
     2227        // compute last iteration condition
     2228        last = (pathname[nb_read] == 0);
     2229
     2230#if (GIET_DEBUG_FAT & 1)
     2231if ( _get_proctime() > GIET_DEBUG_FAT )
     2232_printf("\n[DEBUG FAT] _get_inode_from_path() : got name <%s>\n", name );
     2233#endif
     2234
     2235        // get child inode from parent directory
     2236        code = _get_child_from_parent( parent,
     2237                                       name,
     2238                                       &child );
     2239
     2240        // we  need to find the child inode for all non terminal names
     2241        if ( (code == 2) || ((code == 1 ) && (last == 0)) )
     2242        {
     2243
     2244#if (GIET_DEBUG_FAT & 1)
     2245if ( _get_proctime() > GIET_DEBUG_FAT )
     2246_printf("\n[DEBUG FAT] _get_inode_from_path() : neither parent, nor child found for <%s>\n",
     2247        pathname );
     2248#endif
     2249            return 2;  // error : parent inode not found
     2250        }
     2251       
     2252        // update parent if not the last iteration
     2253        if ( last == 0 ) parent = child;
     2254
     2255    } // end while
     2256
     2257    // returns inode pointer
     2258    if (code == 0 )
     2259    {
     2260
     2261#if (GIET_DEBUG_FAT & 1)
     2262if ( _get_proctime() > GIET_DEBUG_FAT )
     2263_printf("\n[DEBUG FAT] _get_inode_from_path() : found inode for <%s>\n",
     2264        pathname );
     2265#endif
     2266        *inode  = child;
     2267    }
     2268    else
     2269    {
     2270
     2271#if (GIET_DEBUG_FAT & 1)
     2272if ( _get_proctime() > GIET_DEBUG_FAT )
     2273_printf("\n[DEBUG FAT] _get_inode_from_path() : found only parent inode for <%s>\n",
     2274        pathname );
     2275#endif
     2276        *inode  = parent;
     2277    }
     2278
     2279    return code;                 // can be 0 (found) or 1 (not found)
     2280
     2281}  // end _get_inode_from_path()
     2282
     2283
     2284
     2285
     2286//////////////////////////////////////////////////////////////
     2287static unsigned int _remove_node_from_fs( fat_inode_t* inode )
     2288{
     2289    // remove entry in parent directory
     2290    if ( _remove_dir_entry( inode ) ) return 1;
     2291
     2292    // update parent directory on device
     2293    if ( _update_device_from_cache( inode->parent->levels,
     2294                                    inode->parent->cache,
     2295                                    inode->parent->name ) ) return 1;
     2296
     2297    // release clusters allocated to file/dir in DATA region
     2298    if ( _clusters_release( inode->cluster ) ) return 1;
     2299
     2300    // release File-Cache
     2301    if ( _release_cache_memory( inode->cache,
     2302                                inode->levels ) ) return 1;
     2303
     2304    // remove inode from Inode-Tree
     2305    _remove_inode_from_tree( inode );
     2306
     2307    // release inode
     2308    _free ( inode );
     2309
     2310    return 0;
     2311}  // end _remove_node_from_fs()
     2312
     2313
     2314//////////////////////////////////////////////////////////////////
     2315static unsigned int _next_cluster_no_cache( unsigned int   cluster,
     2316                                            unsigned int*  next )
     2317{
     2318    // compute cluster_id and slot_id
     2319    // each cluster contains 1024 slots (4 bytes per slot)
     2320    unsigned int cluster_id  = cluster >> 10;
     2321    unsigned int slot_id     = cluster & 0x3FF;
     2322
     2323    // compute lba of cluster identified by cluster_id
     2324    unsigned int lba = _fat.fat_lba + (cluster_id << 3);
     2325
     2326    // get cluster containing the adressed FAT slot in FAT buffer
     2327    if ( _fat_buffer_fat_lba != lba )
     2328    {
     2329        if ( _fat_ioc_access( 0,         // no descheduling
     2330                              1,         // read
     2331                              lba,
     2332                              (unsigned int)_fat_buffer_fat,
     2333                              8 ) )
     2334        {
     2335            _printf("\n[FAT ERROR] in _next_cluster_no_cache() : "
     2336                    "cannot load lba = %x into fat_buffer\n", lba );
     2337            return 1;
     2338        }
     2339
     2340        _fat_buffer_fat_lba = lba;
     2341    }
     2342
     2343    // return next cluster index
     2344    unsigned int* buf = (unsigned int*)_fat_buffer_fat;
     2345    *next = buf[slot_id];
     2346    return 0;
     2347   
     2348}  // end _next_cluster_no_cache()
     2349
     2350
     2351
     2352
     2353/////////////////////////////////////////////////////////////////
     2354static unsigned int _file_info_no_cache( char*          pathname,
     2355                                         unsigned int*  file_cluster,
     2356                                         unsigned int*  file_size )
     2357{
     2358   
     2359#if (GIET_DEBUG_FAT & 1)
     2360if ( _get_proctime() > GIET_DEBUG_FAT )
     2361_printf("\n[DEBUG FAT] _file_info_no_cache() : enters for path <%s>\n", pathname );
     2362#endif
     2363
     2364    char            name[32];             // buffer for one name in the analysed pathname
     2365    char            lfn1[16];             // buffer for a partial name in LFN entry
     2366    char            lfn2[16];             // buffer for a partial name in LFN entry
     2367    char            lfn3[16];             // buffer for a partial name in LFN entry
     2368    char            cname[32];            // buffer for a full name in a directory entry
     2369    unsigned int    nb_read;              // number of characters analysed in path
     2370    unsigned int    length;               // searched name length
     2371    unsigned int    parent_cluster;       // cluster index for the parent directory
     2372    unsigned int    child_cluster;        // cluster index for the searched file/dir
     2373    unsigned int    child_size;           // size of the searched file/dir
     2374    unsigned int    child_is_dir;         // type of the searched file/dir
     2375    unsigned int    offset;               // offset in a 4 Kbytes buffer
     2376    unsigned int    ord;                  // ORD field in a directory entry
     2377    unsigned int    attr;                 // ATTR field in a directory entry
     2378    unsigned int    lfn;                  // number of lfn entries
     2379    unsigned char*  buf;                  // pointer on a 4 Kbytes buffer
     2380    unsigned int    found;                // name found in current directory entry
     2381
     2382    // Three embedded loops:
     2383    // - scan pathname to extract file/dir names,
     2384    // - for each name, scan the clusters of the parent directory
     2385    // - for each cluster, scan the 4 Kbytes buffer to find the file/dir name
     2386    // The starting point is the root directory (cluster 2)
     2387
     2388    nb_read        = 0;
     2389    parent_cluster = 2;
     2390
     2391    // scan pathname 
     2392    while ( pathname[nb_read] != 0 )   
     2393    {
     2394        // get searched file/dir name
     2395        if ( _get_name_from_path( pathname, name, &nb_read ) ) return 1;
     2396
     2397#if (GIET_DEBUG_FAT & 1)
     2398if ( _get_proctime() > GIET_DEBUG_FAT )
     2399_printf("\n[DEBUG FAT] _file_info_no_cache() : search name <%s>"
     2400        " in cluster %x\n", name , parent_cluster );
     2401#endif
     2402        found  = 0;
     2403        length = _strlen( name );
     2404
     2405        // scan clusters containing the parent directory
     2406        while ( found == 0 ) 
     2407        {
     2408            // compute lba
     2409            unsigned int lba = _cluster_to_lba( parent_cluster );
     2410
     2411            // load one cluster of the parent directory into data_buffer
     2412            if ( _fat_buffer_data_lba != lba )
     2413            {
     2414                if ( _fat_ioc_access( 0,         // no descheduling
     2415                                      1,         // read
     2416                                      lba,
     2417                                      (unsigned int)_fat_buffer_data,
     2418                                      8 ) )
     2419                {
     2420                    _printf("\n[FAT ERROR] in _file_info_no_cache() : "
     2421                            "cannot load lba = %x into data_buffer\n", lba );
     2422                    return 1;
     2423                }
     2424
     2425                _fat_buffer_data_lba = lba;
     2426            }
     2427
     2428            offset = 0;
     2429
     2430            // scan this 4 Kbytes buffer
     2431            while ( (offset < 4096) && (found == 0) )
     2432            {
     2433                buf  = _fat_buffer_data + offset;
     2434                attr = _read_entry( DIR_ATTR , buf , 0 );   
     2435                ord  = _read_entry( LDIR_ORD , buf , 0 );
     2436
     2437                if (ord == NO_MORE_ENTRY)               // no more entry => break
     2438                {
     2439                    found = 2;
     2440                }
     2441                else if ( ord == FREE_ENTRY )           // free entry => skip
     2442                {
     2443                    offset = offset + 32;
     2444                }
     2445                else if ( attr == ATTR_LONG_NAME_MASK ) // LFN entry => get partial name
     2446                {
     2447                    unsigned int seq = ord & 0x3;
     2448                    lfn = (seq > lfn) ? seq : lfn;   
     2449                    if      ( seq == 1 ) _get_name_from_long( buf, lfn1 );
     2450                    else if ( seq == 2 ) _get_name_from_long( buf, lfn2 );
     2451                    else if ( seq == 3 ) _get_name_from_long( buf, lfn3 );
     2452                    offset = offset + 32;
     2453                }
     2454                else                                    // NORMAL entry
     2455                {
     2456                    // build the full mame for current directory entry
     2457                    if      ( lfn == 0 )
     2458                    {
     2459                        _get_name_from_short( buf , cname );
     2460                    }
     2461                    else if ( lfn == 1 )
     2462                    {
     2463                        _strcpy( cname      , lfn1 );
     2464                    }   
     2465                    else if ( lfn == 2 )
     2466                    {
     2467                        _strcpy( cname      , lfn1 );
     2468                        _strcpy( cname + 13 , lfn2 );
     2469                    }
     2470                    else if ( lfn == 3 )
     2471                    {
     2472                        _strcpy( cname      , lfn1 );
     2473                        _strcpy( cname + 13 , lfn2 );
     2474                        _strcpy( cname + 26 , lfn3 );
     2475                    }
     2476                   
     2477                    // test if extracted name == searched name
     2478                    if ( _strncmp( name , cname , length ) == 0 )
     2479                    {
     2480                        child_cluster = (_read_entry( DIR_FST_CLUS_HI , buf , 1 ) << 16) |
     2481                                        (_read_entry( DIR_FST_CLUS_LO , buf , 1 )      ) ;
     2482                        child_is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     2483                        child_size    = _read_entry( DIR_FILE_SIZE , buf , 1 );
     2484                        found         = 1;
     2485                    }
     2486                    offset = offset + 32;
     2487                    lfn = 0;
     2488                }
     2489            }  // en loop on directory entries
     2490           
     2491            // compute next cluster index
     2492            unsigned int next;
     2493            if ( _next_cluster_no_cache ( parent_cluster , &next ) ) return 1;
     2494            parent_cluster = next;
     2495        } // end loop on clusters
     2496
     2497        if ( found == 2 )  // found end of directory => error
     2498        {
     2499            _printf("\n[FAT ERROR] in _file_info_no_cache() : <%s> not found\n",
     2500                    name );
     2501            return 1;
     2502        }
     2503 
     2504        // check type
     2505        if ( ((pathname[nb_read] == 0) && (child_is_dir != 0)) ||
     2506             ((pathname[nb_read] != 0) && (child_is_dir == 0)) )
     2507        {
     2508            _printf("\n[FAT ERROR] in _file_info_no_cache() : illegal type for <%s>\n", name );
     2509            return 1;
     2510        }
     2511
     2512        // update parent_cluster for next name
     2513        parent_cluster = child_cluster;
     2514
     2515    }  // end loop on names
     2516
     2517#if (GIET_DEBUG_FAT & 1)
     2518if ( _get_proctime() > GIET_DEBUG_FAT )
     2519_printf("\n[DEBUG FAT] _file_info_no_cache() : success for <%s> / "
     2520        "file_size = %x / file_cluster = %x\n", pathname, child_size, child_cluster );
     2521#endif
     2522
     2523    // return file cluster and size
     2524    *file_size    = child_size;
     2525    *file_cluster = child_cluster;
     2526    return 0;
     2527
     2528}  // end _file_info_no_cache()
     2529
     2530
     2531
     2532/////////////////////////////////////////////////////////////////////////////
     2533/////////////////////////////////////////////////////////////////////////////
     2534//             Extern functions                                               
     2535/////////////////////////////////////////////////////////////////////////////
     2536/////////////////////////////////////////////////////////////////////////////
     2537
     2538
     2539/////////////////////////////////////////////////////////////////////////////
     2540// This function initializes the FAT structures.
     2541// - The Fat-Descriptor is always initialised.
     2542// - The dynamically allocated structures (the Inode-Tre, the Fat_Cache,
     2543//   and the File-Cache for the root directory) are only allocated
     2544//   and initialised if the "kernel_mode" argument is set.
     2545/////////////////////////////////////////////////////////////////////////////
     2546// Implementation note:
     2547// This function is called twice, by the boot-loader, and by the kernel_init.
     2548// It does not use dynamic memory allocation from the distributed heap.
     2549// It use informations found in the boot sector and FS-INFO sector.
     2550// that are loaded in the Fat-Descriptor temporary block_buffer.
     2551/////////////////////////////////////////////////////////////////////////////
     2552// Returns 0 if success.
     2553// Returns -1 if error.
     2554/////////////////////////////////////////////////////////////////////////////
     2555int _fat_init( unsigned int kernel_mode ) 
     2556{
    7782557
    7792558#if GIET_DEBUG_FAT
    7802559if ( _get_proctime() > GIET_DEBUG_FAT )
    781 _printf("\n[DEBUG FAT] _update_fat() : cluster = %x / value = %x\n",
    782         cluster, value );
    783 #endif
    784 
    785     // update FAT cache in case of miss
    786     if ( lba != _fat.cache_lba ) 
    787     {
    788         if ( _fat_ioc_access( use_irq,
    789                               1,                 // read
    790                               lba,
    791                               (unsigned int)_fat.fat_cache,
    792                               1 ) )              // one sector
    793         {
    794             _printf("\n[FAT_ERROR] in _update_fat() cannot read block %x\n",
    795                     lba );
    796             return 1;
    797         }
    798         _fat.cache_lba = lba;
    799     }
    800 
    801     _write_entry( ((cluster % 128) << 2), 4, _fat.fat_cache, value );
    802 
    803     // write bloc to FAT
    804     if ( _fat_ioc_access( use_irq,
    805                           0,                // write
    806                           lba,
    807                           (unsigned int)_fat.fat_cache,
    808                           1 ) )             // one sector
    809     {
    810         _printf("\n[FAT_ERROR] in _update_fat() cannot write block %x\n",
    811                 lba );
    812         return 1;
    813     }
     2560_printf("\n[DEBUG FAT] _fat_init() : enters at cycle %d\n", _get_proctime() );
     2561#endif
     2562
     2563    // FAT initialisation should be done only once
     2564    if ( _fat.initialised == FAT_INITIALISED )
     2565    {
     2566        _printf("\n[FAT ERROR] in _fat_init() : FAT already initialised\n");
     2567        return -1;
     2568    }
     2569
     2570    // load Boot sector (VBR) into FAT buffer
     2571    if ( _fat_ioc_access( 0,                                  // no descheduling
     2572                          1,                                  // read
     2573                          0,                                  // block index
     2574                          (unsigned int)_fat.block_buffer,
     2575                          1 ) )                               // one block
     2576    {
     2577        _printf("\n[FAT ERROR] in _fat_init() cannot load VBR\n");
     2578        return -1;
     2579    }
     2580
     2581    _fat.block_buffer_lba = 0;
     2582   
     2583#if GIET_DEBUG_FAT
     2584if ( _get_proctime() > GIET_DEBUG_FAT )
     2585{
     2586    _printf("\n[DEBUG FAT] _fat_init() : Boot sector loaded\n");
     2587    _display_one_block( _fat.block_buffer, "block device", _fat.block_buffer_lba );
     2588}
     2589#endif
     2590
     2591    // checking various FAT32 assuptions from boot sector
     2592    if( _read_entry( BPB_BYTSPERSEC, _fat.block_buffer, 1 ) != 512 )
     2593    {
     2594        _printf("\n[FAT ERROR] The sector size must be 512 bytes\n");
     2595        return -1;
     2596    }
     2597    if( _read_entry( BPB_SECPERCLUS, _fat.block_buffer, 1 ) != 8 )
     2598    {
     2599        _printf("\n[FAT ERROR] The cluster size must be 8 blocks\n");
     2600        return -1;
     2601    }
     2602    if( _read_entry( BPB_NUMFATS, _fat.block_buffer, 1 ) != 1 )
     2603    {
     2604        _printf("\n[FAT ERROR] The number of FAT copies in FAT region must be 1\n");
     2605        return -1;
     2606    }
     2607    if( (_read_entry( BPB_FAT32_FATSZ32, _fat.block_buffer, 1 ) & 0xF) != 0 )
     2608    {
     2609        _printf("\n[FAT ERROR] The FAT region must be multiple of 16 sectors\n");
     2610        return -1;
     2611    }
     2612    if( _read_entry( BPB_FAT32_ROOTCLUS, _fat.block_buffer, 1 ) != 2 )
     2613    {
     2614        _printf("\n[FAT ERROR] The root directory must be at cluster 2\n");
     2615        return -1;
     2616    }
     2617
     2618    // initialise Fat-Descriptor from VBR
     2619    _fat.sector_size         = 512;
     2620    _fat.cluster_size        = 4096;
     2621    _fat.fat_sectors         = _read_entry( BPB_FAT32_FATSZ32 , _fat.block_buffer , 1 );
     2622    _fat.fat_lba             = _read_entry( BPB_RSVDSECCNT , _fat.block_buffer , 1 );
     2623    _fat.data_sectors        = _fat.fat_sectors << 10;
     2624    _fat.data_lba            = _fat.fat_lba + _fat.fat_sectors;
     2625    _fat.fs_info_lba         = _read_entry( BPB_FAT32_FSINFO , _fat.block_buffer , 1 );
     2626    _fat_buffer_fat_lba      = 0xFFFFFFFF;
     2627    _fat_buffer_data_lba     = 0xFFFFFFFF;
     2628    _fat.initialised         = FAT_INITIALISED;
     2629
     2630    // load FS_INFO sector into FAT buffer
     2631    if ( _fat_ioc_access( 0,                                // no descheduling
     2632                          1,                                // read
     2633                          _fat.fs_info_lba,                 // lba
     2634                          (unsigned int)_fat.block_buffer,
     2635                          1 ) )                             // one block
     2636    {
     2637        _printf("\n[FAT ERROR] in _fat_init() cannot load FS_INFO Sector\n");
     2638        return -1;
     2639    }
     2640
     2641    _fat.block_buffer_lba = _fat.fs_info_lba;
     2642
     2643#if GIET_DEBUG_FAT
     2644if ( _get_proctime() > GIET_DEBUG_FAT )
     2645{
     2646    _printf("\n[DEBUG FAT] _fat_init() : FS-INFO sector loaded\n");
     2647    _display_one_block( _fat.block_buffer, "block device", _fat.block_buffer_lba );
     2648}
     2649#endif
     2650
     2651    // initialise Fat-Descriptor from FS_INFO
     2652    _fat.free_clusters_number   = _read_entry( FS_FREE_CLUSTERS    , _fat.block_buffer, 1);
     2653    _fat.first_free_cluster     = _read_entry( FS_FREE_CLUSTER_HINT, _fat.block_buffer, 1);
     2654
     2655    // This is done only when the _fat_init() is called in kernel mode
     2656
     2657    if ( kernel_mode )
     2658    {
     2659        unsigned int   n;
     2660
     2661        // allocate and initialise the Inode-Tree root
     2662        fat_inode_t*      inode  = _malloc( sizeof(fat_inode_t) );
     2663        fat_cache_node_t* cache  = _malloc( sizeof(fat_cache_node_t) );
     2664
     2665        inode->parent   = NULL;        // no parent
     2666        inode->next     = NULL;        // no brother
     2667        inode->child    = NULL;        // children come later
     2668        inode->cache    = cache;       // empty cache
     2669        inode->cluster  = 2;           // forced value
     2670        inode->size     = 0;           // no size for a directory
     2671        inode->count    = 0;           // children come later
     2672        inode->dentry   = 0;           // no parent => no dentry
     2673        inode->levels   = 1;           // one level cache
     2674        inode->is_dir   = 1;           // it's a directory
     2675        _strcpy( inode->name , "/" ); 
     2676
     2677        for ( n = 0 ; n < 64 ; n ++ )  cache->children[n] = NULL;
     2678
     2679        _fat.inode_tree_root = inode;
     2680
     2681        // initialise the lock
     2682        _spin_lock_init( &_fat.fat_lock );
     2683
     2684        // initialise File Descriptor Array
     2685        for( n = 0 ; n < GIET_OPEN_FILES_MAX ; n++ ) _fat.fd[n].allocated = 0;
     2686
     2687        // initialise fat_cache root
     2688        fat_cache_node_t*  fat_cache_root = _malloc( sizeof(fat_cache_node_t) );
     2689        _fat.fat_cache_root   = fat_cache_root;
     2690        _fat.fat_cache_levels = _get_levels_from_size( _fat.fat_sectors << 9 );
     2691        for ( n = 0 ; n < 64 ; n++ ) _fat.fat_cache_root->children[n] = NULL;
     2692
     2693    }  // end if kernel_mode
     2694
     2695#if GIET_DEBUG_FAT
     2696if ( _get_proctime() > GIET_DEBUG_FAT )
     2697_display_fat_descriptor();
     2698#endif
    8142699
    8152700    return 0;
    816 } // end update_fat()
    817 
    818 //////////////////////////////////////////////////////////////////////////////////
    819 // This function allocate count clusters to a file by calling the
    820 // _update_fat function that takes care to update the chaining of clusters.
    821 // return 0 if success, -1 if failure
    822 //////////////////////////////////////////////////////////////////////////////////
    823 static inline
    824 int _fat_allocate( unsigned int use_irq,
    825                    unsigned int fd_id,
    826                    unsigned int count )
    827 {
    828     unsigned int next_cluster = _fat.fd[fd_id].first_cluster;    // first cluster
    829     unsigned int cluster_to_allocate = count;                   // to allocate
    830     unsigned int last_cluster_file;                             // Last cluster
    831     unsigned int free_cluster = _fat.last_cluster_allocated + 1; // First free
    832 
    833     // Check if free_cluster is really free (must be true)
    834     if ( _get_next_cluster( use_irq , free_cluster ) != FREE_CLUSTER)
    835     {
    836         _printf("\n[FAT ERROR] in _fat_allocate() : first free cluster not free\n");
    837         return -1;
    838     }
    839     // Check if FAT contains enough cluster free for this allocation
    840     if ( count > _fat.number_free_cluster )
    841     {
    842         _printf("\n[FAT ERROR] in _fat_allocate() : Not enough free cluster(s)\n");
    843         return -1;
    844     }
    845 
    846 #if GIET_DEBUG_FAT
    847 if ( _get_proctime() > GIET_DEBUG_FAT )
    848 _printf("\n[DEBUG FAT] _fat_allocate() for fd = %d\n", fd_id );
    849 #endif
    850 
    851     // Get the last cluster allocated for the file (seek END_OF_CHAIN_CLUSTER).
    852     do
    853     {
    854         last_cluster_file = next_cluster;
    855         next_cluster      = _get_next_cluster( use_irq , next_cluster );
    856     }
    857     while ( next_cluster < END_OF_CHAIN_CLUSTER );
    858 
    859     // Loop on the number of clusters to be allocated
    860     while ( cluster_to_allocate > 0 )
    861     {
    862 
    863 #if GIET_DEBUG_FAT
    864 if ( _get_proctime() > GIET_DEBUG_FAT )
    865 _printf("\n[DEBUG FAT] cluster to update = %x / free cluster = %x / count = %d\n",
    866         last_cluster_file , free_cluster , cluster_to_allocate );
    867 #endif
    868 
    869         // update, in the FAT, the value of last cluster allocated by the index
    870         // of free cluster.
    871         if ( _update_fat( use_irq , last_cluster_file , free_cluster ) )
    872         {
    873             _printf("\n[FAT ERROR] in _fat_allocate() : update fat failed\n");
    874             return -1;
    875         }
    876 
    877         cluster_to_allocate = cluster_to_allocate - 1;
    878         // Last cluster allocated is then free_cluster
    879         last_cluster_file = free_cluster;
    880 
    881         // Last cluster to allocate done, then we must close the chain of clusters
    882         if ( cluster_to_allocate == 0 )
    883         {
    884             // update, in the FAT, the value of the last cluster allocated by
    885             // END_OF_CHAIN_CLUSTER
    886             if ( _update_fat( use_irq , last_cluster_file , END_OF_CHAIN_CLUSTER ) )
    887             {
    888                 _printf("\n[FAT ERROR] in _fat_allocate() : update fat failed\n");
    889                 return -1;
    890             }
    891         }
    892 
    893         free_cluster = free_cluster + 1;
    894 
    895         // Check if free_cluster is really free (must be true)
    896         if ( _get_next_cluster( use_irq , free_cluster ) != FREE_CLUSTER)
    897         {
    898             _printf("\n[FAT ERROR] in _fat_allocate() : free_cluster not free\n");
    899             return -1;
    900         }
    901     }
    902 
    903     // Update field number_free_cluster and last_cluster_allocated
    904     // of structure fat for next fat_allocate
    905     _fat.last_cluster_allocated = last_cluster_file;
    906     _fat.number_free_cluster    = _fat.number_free_cluster - count;
    907 
    908     if ( _update_fs_info( use_irq ) )
    909     {
    910         _printf("\n[FAT ERROR] in _fat_allocate() : update fs_info failed\n");
    911         return -1;
    912     }
    913 
    914     return 0;
    915 }  // end _fat_allocate()
    916 
    917 //////////////////////////////////////////////////////////////////////////////////
    918 // This function read the blocks defined by the cluster index argument, in a data
    919 // region containing a directory to search the name of a file/firectory.
    920 // It returns the cluster index of the file/directory when the name has been found,
    921 // as well as the file size, and the lba.
    922 // We consider 3 types of directory entries:
    923 // - SFN : directory entry associated to a Short File Name (8.3)
    924 // - LFN : directory entry associated to a Long File Name
    925 // - XTN : directory entry containing only a name extension for a Long File Name
    926 // The cluster index is always stored in a SFN or LFN entry.
    927 // Return cluster index if name found / Return -1 if not found.
    928 //////////////////////////////////////////////////////////////////////////////////
    929 static
    930 int _scan_directory( unsigned int   use_irq,         // use descheduling mode
    931                      unsigned int   cluster,         // cluster of dir_entry
    932                      char*          file_name,       // searched file/dir name
    933                      unsigned int*  file_size,       // file size
    934                      unsigned int*  lba_dir_entry )  // lba of dir_entry
    935 {
    936     char dir_entry[32];       // buffer to store a full directory_entry
    937     char name_entry[14];      // buffer to store a 13 characters (partial) name
    938 
    939     char sfn_string[12]    = {[0 ... 10] = ' ', '\0'};  // buffer Short File Name
    940     unsigned int  is_sfn   = is_short(file_name, sfn_string); // file_name is short
    941     unsigned int  offset   = 0;                         // byte offset in block
    942     unsigned int  block_id = _fat.sectors_per_cluster;  // sector index
    943     unsigned int  lba      = cluster_to_lba(cluster);   // lba of cluster
    944     unsigned int  attr     = 0;                         // dir entry attribute
    945     unsigned int  ord      = 0;                         // dir entry sequence
    946     unsigned int  found    = 0;                         // searched name found
    947     unsigned int  long_name_found = 0;                  // matching XTN found
    948     unsigned int  searched_cluster;                     // searched cluster index
     2701}  // end _fat_init()
     2702
     2703
     2704
     2705
     2706///////////////////////////////////////////////////////////////////////////////
     2707// This function implements the giet_fat_open() system call.
     2708// The semantic is similar to the UNIX open() function, but only the O_CREATE
     2709// and O_RDONLY flags are supported. The UNIX access rights are not supported.
     2710// If the file does not exist in the specified directory, it is created.
     2711// If the specified directory does not exist, an error is returned.
     2712// It allocates a file descriptor to the calling task, for the file identified
     2713// by "pathname". If several tasks try to open the same file, each task 
     2714// obtains a private file descriptor.
     2715// A node name (file or directory) cannot be larger than 31 characters.
     2716///////////////////////////////////////////////////////////////////////////////
     2717// Returns file descriptor index if success
     2718// Returns a negative value if error:
     2719//   -1  :  "fat not initialised"
     2720//   -2  :  "path to parent not found"
     2721//   -3  :  "one name in path too long"
     2722//   -4  :  "file not found"
     2723//   -5  :  "Cannot update parent directory"
     2724//   -6  :  "Cannot update DATA region"
     2725//   -7  :  "Cannot update FAT region"
     2726//   -8  :  "Cannot update FS_INFO sector"
     2727//   -9  :  "file descriptor array full"
     2728///////////////////////////////////////////////////////////////////////////////
     2729int _fat_open( char*        pathname,     // absolute path from root
     2730               unsigned int flags )       // O_CREATE and O_RDONLY
     2731{
     2732    unsigned int         fd_id;            // index in File-Descriptor-Array
     2733    unsigned int         code;             // error code
     2734    fat_inode_t*         inode;            // anonymous inode pointer
     2735    fat_inode_t*         child;            // pointer on searched file inode
     2736    fat_inode_t*         parent;           // pointer on parent directory inode
     2737   
     2738    // get flags
     2739    unsigned int create    = ((flags & O_CREATE) != 0);
     2740    unsigned int read_only = ((flags & O_RDONLY) != 0);
    9492741
    9502742#if GIET_DEBUG_FAT
     
    9542746unsigned int p       = procid & ((1<<P_WIDTH)-1);
    9552747if ( _get_proctime() > GIET_DEBUG_FAT )
    956 _printf("\n[DEBUG FAT] _scan_directory() : P[%d,%d,%d] enters for %s\n",
    957       x, y, p, file_name );
    958 #endif
    959 
    960     unsigned int  i;
    961     for( i = 0 ; i < 32 ; i++ ) dir_entry[i]  = 0;
    962     for( i = 0 ; i < 14 ; i++ ) name_entry[i] = 0;
    963 
    964     // load first sector from DATA region into FAT cache
    965     // other sectors will be loaded inside loop as required
    966     if( _fat_ioc_access( use_irq,
    967                          1,               // read
    968                          lba,
    969                          (unsigned int)_fat.fat_cache,
    970                          1 ) )            // one sector
    971     {
    972         _printf("[\nFAT ERROR] in _scan_directory() : cannot read sector %x\n",
    973                 lba );
     2748_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] enters for path <%s> / "
     2749        " create = %d / read_only = %d\n",
     2750        x, y, p, pathname , create , read_only );
     2751#endif
     2752
     2753    // checking FAT initialised
     2754    if( _fat.initialised != FAT_INITIALISED )
     2755    {
     2756        _printf("\n[FAT ERROR] in _fat_open() : FAT not initialised\n");
    9742757        return -1;
    9752758    }
    976     _fat.cache_lba = lba;
    977 
    978 #if GIET_DEBUG_FAT
    979 if ( (_get_proctime() > GIET_DEBUG_FAT) && (GIET_DEBUG_FAT & 0x1) )
    980 _display_fat_cache();
    981 #endif
    982 
    983     // in this loop we scan all names in the directory identified by cluster index
    984     // - the offset increment is an integer number of directory entry (32 bytes)
    985     // - the exit condition is success (name found) or failure (end of directory)
    986     while( found == 0 )
    987     {
    988         // load a new sector if required
    989         if (offset >= 512)             
    990         {
    991             if ( block_id )           // not a new cluster
    992             {
    993                 lba += 1;
    994                 block_id --;
    995             }
    996             else                                          // get next cluster
    997             {
    998                 cluster = _get_next_cluster( use_irq , cluster );
    999 
    1000                 if ( cluster >= END_OF_CHAIN_CLUSTER  ) return END_OF_CHAIN_CLUSTER;
    1001 
    1002                 lba      = cluster_to_lba(cluster);
    1003                 block_id = _fat.sectors_per_cluster;
    1004             }
    1005             if( _fat_ioc_access( use_irq,
    1006                                  1,               // read
    1007                                  lba,
    1008                                  (unsigned int)_fat.fat_cache,
    1009                                  1 ) )            // one sector
    1010             {
    1011                 _printf("\n[FAT ERROR] in _scan_directory() : cannot read sector %x\n",
    1012                         lba);
    1013                 return -1;
    1014             }
    1015             _fat.cache_lba = lba;
    1016             block_id--;
    1017             offset = offset % 512;
    1018         }
    1019 
    1020         // store the directory entry pointed by offset in dir_entry buffer,
    1021         // if it a possible candidate for the searched name
    1022 
    1023         attr = _read_entry( DIR_ATTR, _fat.fat_cache + offset, 0);   
    1024         ord  = _read_entry( LDIR_ORD, _fat.fat_cache + offset, 0);
    1025 
    1026         if ( is_sfn == 1 )                                // searched name is short
    1027         {
    1028             if      ( (ord != FREE_ENTRY ) &&
    1029                       (ord != NO_MORE_ENTRY) &&
    1030                       (attr == ATTR_LONG_NAME_MASK) )    // EXT entry : skipped
    1031             {
    1032                 offset     = offset + ((ord & 0xF) * DIR_ENTRY_SIZE);
    1033             }
    1034             else if ( (attr != ATTR_LONG_NAME_MASK) &&
    1035                       (ord  != FREE_ENTRY) &&
    1036                       (ord  != NO_MORE_ENTRY ) )         // SFN entry : to be checked
    1037             {
    1038                 memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );   
    1039 
    1040                 get_name_from_short( dir_entry, name_entry );
    1041 
    1042                 if ( _strncmp( (char*)sfn_string,
    1043                                (char*)name_entry, 13 ) == 0 )  // short name found
    1044                 {
    1045                     found = 1;
    1046                 }
    1047                 else
    1048                 {
    1049                     offset = offset + DIR_ENTRY_SIZE;
    1050                 }
    1051             }
    1052             else if (ord == NO_MORE_ENTRY )              // end of directory : return
    1053             {
    1054                 return END_OF_CHAIN_CLUSTER;
    1055             }
    1056         }
    1057         else                                      // searched name is long
    1058         {
    1059             if( (attr == ATTR_LONG_NAME_MASK) &&
    1060                 (ord != FREE_ENTRY) &&
    1061                 (ord != NO_MORE_ENTRY) )                 // EXT entry : to be checked
    1062             {
    1063                 memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );
    1064 
    1065                 get_name_from_long( dir_entry, name_entry );
    1066 
    1067                 unsigned shift = ((ord & 0xf) - 1) * 13;
    1068                 if ( _strncmp( (char*)(file_name + shift),
    1069                                (char*)name_entry, 13 ) == 0 )  // matching EXT
    1070                 {
    1071                     if( (ord & 0xf) == 1 )                    // long name found
    1072                     {
    1073                         long_name_found = 1;
    1074                     }
    1075                 }
    1076                 offset = offset + DIR_ENTRY_SIZE;
    1077             }
    1078             else if( (attr != ATTR_LONG_NAME_MASK) &&
    1079                      (ord  != FREE_ENTRY) &&
    1080                      (ord  != NO_MORE_ENTRY) )
    1081             {
    1082                 if ( long_name_found )                   // LFN entry
    1083                 {
    1084                     memcpy( dir_entry, _fat.fat_cache + offset, DIR_ENTRY_SIZE );
    1085                     found = 1;
    1086                 }
    1087                 else                                     // SFN entry: must be skipped
    1088                 {
    1089                     offset = offset + DIR_ENTRY_SIZE;
    1090                 }
    1091             }
    1092             else if (ord == NO_MORE_ENTRY )                              // end of directory : return
    1093             {
    1094                 return END_OF_CHAIN_CLUSTER;
    1095             }
    1096         }
    1097     }  // end while
    1098 
    1099     // returns cluster index
    1100     *file_size       = _read_entry( DIR_FILE_SIZE, dir_entry, 1 );
    1101     *lba_dir_entry   = lba;
    1102     searched_cluster = (_read_entry( DIR_FST_CLUS_HI, dir_entry, 1 ) << 16) |
    1103                        (_read_entry( DIR_FST_CLUS_LO, dir_entry, 1 )      ) ;
     2759
     2760    // takes the lock
     2761    _spin_lock_acquire( &_fat.fat_lock );
     2762
     2763    // get inode pointer
     2764    code = _get_inode_from_path( pathname , &inode );
     2765
     2766    if ( code == 2 ) 
     2767    {
     2768        _spin_lock_release( &_fat.fat_lock );
     2769        _printf("\n[FAT ERROR] in _fat_open() : path to parent not found"
     2770                " for file <%s>\n", pathname );
     2771        return -2;
     2772    }
     2773    else if ( code == 3 ) 
     2774    {
     2775        _spin_lock_release( &_fat.fat_lock );
     2776        _printf("\n[FAT ERROR] in _fat_open() : one name in path too long"
     2777                " for file <%s>\n", pathname );
     2778        return -3;
     2779    }
     2780    else if ( (code == 1) && (create == 0) )   
     2781    {
     2782        _spin_lock_release( &_fat.fat_lock );
     2783        _printf("\n[FAT ERROR] in _fat_open() : file not found"
     2784                " for file <%s>\n", pathname );
     2785        return -4;
     2786    }
     2787    else if ( (code == 1) && (create != 0) )   // file name not found => create
     2788    {
     2789        // set parent inode pointer
     2790        parent = inode;
    11042791
    11052792#if GIET_DEBUG_FAT
    11062793if ( _get_proctime() > GIET_DEBUG_FAT )
    1107 _printf("\n[DEBUG FAT] _scan_directory() : P[%d,%d,%d] found %s"
    1108         " : cluster = %x\n", x, y, p, file_name, searched_cluster );
    1109 #endif
    1110 
    1111     return searched_cluster;
    1112 } // end _scan_directory()
    1113 
    1114 
    1115 //////////////////////////////////////////////////////////////////////
    1116 // This function create a new entry in a directory identified
    1117 // by "dir_cluster". The name is defined by "name".
    1118 // The type (dir/file) is defined by "is_file".
    1119 // Returns cluster index if success, Returns -1 if error.
    1120 //////////////////////////////////////////////////////////////////////
    1121 static int _fat_create( char*           name,
    1122                         unsigned int    is_file,
    1123                         unsigned int    dir_cluster )
    1124 {
    1125     _printf("\n[FAT ERROR] _fat_create() not implemented\n");
     2794_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] create a new file <%s>\n",
     2795        x , y , p , pathname );
     2796#endif
     2797
     2798        // get new file name / error check already done by _get_inode_from_path()
     2799        char name[32];       
     2800        _get_last_name( pathname , name );
     2801
     2802        // allocate a new inode and an empty Cache-File
     2803        child = _allocate_one_inode( name,
     2804                                     0,                         // not a directory
     2805                                     END_OF_CHAIN_CLUSTER_MAX,  // no cluster allocated
     2806                                     0,                         // size : new file is empty
     2807                                     0,                         // count incremented later
     2808                                     0,                         // dentry set by add_dir_entry
     2809                                     1 );                       // cache_allocate
     2810
     2811        // introduce inode into Inode-Tree
     2812        _add_inode_in_tree( child , parent );
     2813
     2814        // add an entry in the parent directory Cache_file
     2815        if ( _add_dir_entry( child , parent ) )
     2816        {
     2817            _spin_lock_release( &_fat.fat_lock );
     2818            _printf("\n[FAT ERROR] in _fat_open() : cannot update parent directory"
     2819                    " for file <%s>\n" , pathname );
     2820            return -5;
     2821        }
     2822
     2823        // update DATA region on block device for parent directory
     2824        if ( _update_device_from_cache( parent->levels,
     2825                                        parent->cache,
     2826                                        parent->name ) )
     2827        {
     2828            _spin_lock_release( &_fat.fat_lock );
     2829            _printf("\n[FAT ERROR] in _fat_open() : cannot update DATA region "
     2830                    " for parent of file <%s>\n", pathname );
     2831            return -6;
     2832        }
     2833
     2834        // update FAT region on block device
     2835        if ( _update_device_from_cache( _fat.fat_cache_levels,
     2836                                        _fat.fat_cache_root,
     2837                                        "FAT" ) )
     2838        {
     2839            _spin_lock_release( &_fat.fat_lock );
     2840            _printf("\n[FAT ERROR] in _fat_open() : cannot update FAT region"
     2841                    " for file <%s>\n", pathname );
     2842            return -7;
     2843        }
     2844
     2845        // update FS_INFO sector
     2846        if ( _update_fs_info() )
     2847        {
     2848            _spin_lock_release( &_fat.fat_lock );
     2849            _printf("\n[FAT ERROR] in _fat_open() : cannot update FS-INFO"
     2850                    " for file <%s>\n", pathname );
     2851            return -8;
     2852        }
     2853    }
     2854    else // code == 0
     2855    {
     2856        // set searched file inode pointer
     2857        child = inode;
     2858
     2859#if GIET_DEBUG_FAT
     2860if ( _get_proctime() > GIET_DEBUG_FAT )
     2861_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] found file <%s> on device : inode = %x\n",
     2862        x , y , p , pathname , child );
     2863#endif
     2864
     2865    }
     2866
     2867    // Search an empty slot in file descriptors array
     2868    fd_id = 0;
     2869    while ( (_fat.fd[fd_id].allocated) != 0 && (fd_id < GIET_OPEN_FILES_MAX) )
     2870    {
     2871        fd_id++;
     2872    }
     2873
     2874    // set file descriptor if an empty slot has been found
     2875    if ( fd_id < GIET_OPEN_FILES_MAX )
     2876    {
     2877        // update file descriptor
     2878        _fat.fd[fd_id].allocated  = 1;
     2879        _fat.fd[fd_id].seek       = 0;
     2880        _fat.fd[fd_id].read_only  = read_only;
     2881        _fat.fd[fd_id].inode      = child;
     2882
     2883        // increment the refcount
     2884        child->count = child->count + 1;
     2885
     2886        // releases the lock
     2887        _spin_lock_release( &_fat.fat_lock );
     2888
     2889#if GIET_DEBUG_FAT
     2890if ( _get_proctime() > GIET_DEBUG_FAT )
     2891_printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] got fd = %d for <%s> / "
     2892        "read_only = %d\n",
     2893        x , y , p , fd_id , pathname , read_only );
     2894#endif
     2895        return fd_id;
     2896    }
     2897    else
     2898    {
     2899        _spin_lock_release( &_fat.fat_lock );
     2900        _printf("\n[FAT ERROR] in _fat_open() : File-Descriptors-Array full\n");
     2901        return -9;
     2902    }
     2903} // end _fat_open()
     2904
     2905
     2906
     2907
     2908/////////////////////////////////////////////////////////////////////////////////
     2909// This function implements the "giet_fat_close()" system call.
     2910// It decrements the inode reference count, and release the fd_id entry
     2911// in the file descriptors array.
     2912// If the reference count is zero, it writes all dirty clusters on block device,
     2913// and releases the memory allocated to the file_cache: The cache 64-Tree
     2914// infrastructure (depending on file size) is kept, but all buffers and all
     2915// buffer descriptors are released.
     2916/////////////////////////////////////////////////////////////////////////////////
     2917// Returns 0 on success.
     2918// Returns negative value if error:
     2919//  -1  : "FAT not initialised"
     2920//  -2  : "Illegal file descriptor"
     2921//  -3  : "Cannot update DATA region for closed file"
     2922//  -4  : "Cannot release memory"
     2923/////////////////////////////////////////////////////////////////////////////////
     2924int _fat_close( unsigned int fd_id )
     2925{
     2926    // checking FAT initialised
     2927    if( _fat.initialised != FAT_INITIALISED )
     2928    {
     2929        _printf("\n[FAT ERROR] in _fat_close() : FAT not initialised\n");
     2930        return -1;
     2931    }
     2932
     2933    if( (fd_id >= GIET_OPEN_FILES_MAX) )
     2934    {
     2935        _printf("\n[FAT ERROR] in _fat_close() : illegal file descriptor index\n");
     2936        return -2;
     2937    }
     2938
     2939    // takes lock
     2940    _spin_lock_acquire( &_fat.fat_lock );
     2941
     2942    // get the inode pointer
     2943    fat_inode_t*  inode = _fat.fd[fd_id].inode;
     2944
     2945    // decrement reference count
     2946    inode->count = inode->count - 1;
     2947   
     2948#if GIET_DEBUG_FAT
     2949if ( _get_proctime() > GIET_DEBUG_FAT )
     2950_printf("\n[FAT DEBUG] _fat_close() for file <%s> : refcount = %d\n",
     2951        inode->name , inode->count );
     2952#endif
     2953
     2954    // update block device and release File-Cache if no more references
     2955    if ( inode->count == 0 )
     2956    {
     2957        // update all dirty clusters for closed file
     2958        if ( _update_device_from_cache( inode->levels,
     2959                                        inode->cache,
     2960                                        inode->name ) )
     2961        {
     2962            _spin_lock_release( &_fat.fat_lock );
     2963            _printf("\n[FAT ERROR] in _fat_close() : cannot write dirty clusters "
     2964                    "for file <%s>\n", inode->name );
     2965            return -3;
     2966        }
     2967
     2968#if GIET_DEBUG_FAT
     2969if ( _get_proctime() > GIET_DEBUG_FAT )
     2970_printf("\n[FAT DEBUG] _fat_close() update device for file <%s>\n", inode->name );
     2971#endif
     2972
     2973        // update directory dirty clusters for parent directory
     2974        if ( _update_device_from_cache( inode->parent->levels,
     2975                                        inode->parent->cache,
     2976                                        inode->parent->name ) )
     2977        {
     2978            _spin_lock_release( &_fat.fat_lock );
     2979            _printf("\n[FAT ERROR] in _fat_close() : cannot write dirty clusters "
     2980                    "for directory <%s>\n", inode->parent->name );
     2981            return -4;
     2982        }
     2983
     2984#if GIET_DEBUG_FAT
     2985if ( _get_proctime() > GIET_DEBUG_FAT )
     2986_printf("\n[FAT DEBUG] _fat_close() update device for parent directory <%s>\n",
     2987        inode->parent->name );
     2988#endif
     2989
     2990        // release memory allocated to File-Cache
     2991        if ( _release_cache_memory( inode->cache,
     2992                                    inode-> levels ) )
     2993        {
     2994            _spin_lock_release( &_fat.fat_lock );
     2995            _printf("\n[FAT ERROR] in _fat_close() : cannot release cache memory "
     2996                    "for file <%s>\n", _fat.fd[fd_id].inode->name );
     2997            return -5;
     2998        }
     2999
     3000#if GIET_DEBUG_FAT
     3001if ( _get_proctime() > GIET_DEBUG_FAT )
     3002_printf("\n[FAT DEBUG] _fat_close() release memory for File-Cache <%s>\n",
     3003        inode->name );
     3004#endif
     3005
     3006    }
     3007
     3008    // release fd_id entry in file descriptor array
     3009    _fat.fd[fd_id].allocated = 0;
     3010
     3011    // release lock
     3012    _spin_lock_release( &_fat.fat_lock );
     3013
    11263014    return 0;
    1127 }  //end _fat_create()
    1128 
    1129 
    1130 
    1131 ////////////// Extern functions //////////////////////////////////////////
    1132 
    1133 //////////////////////////////////////////////////////////////////////////
    1134 // This function initializes the FAT structure, including the open
    1135 // files descriptors array and the lock protecting the FAT,
    1136 // from informations found in the boot record.
    1137 // This should be done only once.
    1138 //////////////////////////////////////////////////////////////////////////
    1139 // Return 0 if success, exit if failure
    1140 //////////////////////////////////////////////////////////////////////////
    1141 int _fat_init( unsigned int use_irq ) 
    1142 {
     3015} // end fat_close()
     3016
     3017
     3018
     3019
     3020/////////////////////////////////////////////////////////////////////////////////
     3021// This function implements the giet_fat_file_info() system call.
     3022// It returns the size and the current offset value for a file identified
     3023// by the "fd_id" argument.
     3024/////////////////////////////////////////////////////////////////////////////////
     3025// Returns  0 if success.
     3026// Returns negative value if error.
     3027//  -1  : "FAT not initialised"
     3028//  -2  : "Illegal file descriptor"
     3029//  -3  : "File not open"
     3030/////////////////////////////////////////////////////////////////////////////////
     3031int _fat_file_info( unsigned int   fd_id,
     3032                    unsigned int*  size,
     3033                    unsigned int*  offset )
     3034{
     3035    // checking FAT initialised
     3036    if( _fat.initialised != FAT_INITIALISED )
     3037    {
     3038        _printf("\n[FAT ERROR] in _fat_file_info() : FAT not initialised\n");
     3039        return -1;
     3040    }
     3041
     3042
     3043    if( fd_id >= GIET_OPEN_FILES_MAX )
     3044    {
     3045        _printf("\n[FAT ERROR] in _fat_file_info() : illegal file descriptor index\n");
     3046        return -2;
     3047    }
     3048
     3049    if ( _fat.fd[fd_id].allocated == 0 )
     3050    {
     3051        _printf("\n[FAT ERROR] in _fat_file_info() : file <%s> not open\n",
     3052                _fat.fd[fd_id].inode->name );
     3053        return -3;
     3054    }
     3055
     3056    *size   = _fat.fd[fd_id].inode->size;
     3057    *offset = _fat.fd[fd_id].seek; 
     3058    return 0;
     3059
     3060} // end _fat_file_info()
     3061
     3062
     3063
     3064
     3065/////////////////////////////////////////////////////////////////////////////////
     3066// The following function implements the "giet_fat_read()" system call.
     3067// It transfers "count" bytes from the File_Cache associated to the file
     3068// identified by "fd_id", to the user "buffer", from the current file offset.
     3069// It has the same semantic as the UNIX "read()" function.
     3070// In case of miss in the File_Cache, it loads all involved clusters into cache.
     3071/////////////////////////////////////////////////////////////////////////////////
     3072// Returns number of bytes actually transfered if success .
     3073// Returns 0 if EOF encountered (offset + count > file_size).
     3074// Returns a negative value if error:
     3075//   -1 :  "fat not initialised"
     3076//   -2 :  "file not open"
     3077//   -3 :  "cannot load file from device"
     3078/////////////////////////////////////////////////////////////////////////////////
     3079int _fat_read( unsigned int fd_id,     // file descriptor index
     3080               void*        buffer,    // destination buffer
     3081               unsigned int count )    // number of bytes to read
     3082{
     3083    // checking FAT initialised
     3084    if( _fat.initialised != FAT_INITIALISED )
     3085    {
     3086        _printf("\n[FAT ERROR] in _fat_write() : FAT not initialised\n");
     3087        return -1;
     3088    }
     3089
     3090    // check fd_id overflow
     3091    if ( fd_id >= GIET_OPEN_FILES_MAX )
     3092    {
     3093        _printf("\n[FAT ERROR] in _fat_read() : illegal file descriptor\n");
     3094        return -1;
     3095    }
     3096
     3097    // check file is open
     3098    if ( _fat.fd[fd_id].allocated == 0 )
     3099    {
     3100        _printf("\n[FAT ERROR] in _fat_read() : file not open\n");
     3101        return -2;
     3102    }
     3103
     3104    // takes lock
     3105    _spin_lock_acquire( &_fat.fat_lock );
     3106           
     3107    // get file inode pointer and offset
     3108    fat_inode_t* inode  = _fat.fd[fd_id].inode;
     3109    unsigned int seek   = _fat.fd[fd_id].seek;
     3110
     3111    // check count & seek versus file size
     3112    if ( count + seek > inode->size )
     3113    {
     3114        _spin_lock_release( &_fat.fat_lock );
     3115        _printf("\n[FAT ERROR] in _fat_read() : file too small"
     3116                " / seek = %x / count = %x / file_size = %x\n",
     3117                seek , count , inode->size );
     3118        return 0;
     3119    }
     3120
     3121    // compute first_cluster_id and first_byte_to_move
     3122    unsigned int first_cluster_id   = seek >> 12;
     3123    unsigned int first_byte_to_move = seek & 0xFFF;   
     3124
     3125    // compute last_cluster and last_byte_to_move
     3126    unsigned int last_cluster_id   = (seek + count - 1) >> 12;   
     3127    unsigned int last_byte_to_move = (seek + count - 1) & 0xFFF;
    11433128
    11443129#if GIET_DEBUG_FAT
     
    11483133unsigned int p       = procid & ((1<<P_WIDTH)-1);
    11493134if ( _get_proctime() > GIET_DEBUG_FAT )
    1150 _printf("\n[DEBUG FAT] P[%d,%d,%d] enters _fat_init\n",x,y,p);
    1151 #endif
    1152 
    1153     // FAT initialisation should be done only once
    1154     if ( _fat.initialised == FAT_INITIALISED )
    1155     {
    1156         _printf("\n[FAT ERROR] Strange, FAT already initialised...\n");
    1157         _exit();
    1158     }
    1159 
    1160     // load Boot Record (VBR) into fat cache
    1161     if ( _fat_ioc_access( use_irq,
    1162                           1,                   // read
    1163                           0,                   // sector index
    1164                           (unsigned int)_fat.fat_cache,
    1165                           1 ) )                // one sector
    1166     {
    1167         _printf("\n[FAT ERROR] in _fat_init() cannot load VBR\n");
    1168         _exit();
    1169     }
    1170     _fat.cache_lba = 0;
    1171 
    1172 #if GIET_DEBUG_FAT > 1
    1173 if ( _get_proctime() > GIET_DEBUG_FAT )
    1174 _printf("\n[DEBUG FAT] _fat_init() : Boot Sector Loaded\n");
    1175 if ( (_get_proctime() > GIET_DEBUG_FAT) && (GIET_DEBUG_FAT & 0x1) )
    1176 _display_fat_cache();
    1177 #endif
    1178 
    1179     // checking various FAT32 assuptions from boot sector
    1180     if( _read_entry( BPB_BYTSPERSEC, _fat.fat_cache, 1 ) != 512 )
    1181     {
    1182         _printf("\n[FAT ERROR] The sector size must be 512 bytes\n");
    1183         _exit();
    1184     }
    1185     if( _read_entry( BPB_NUMFATS, _fat.fat_cache, 1 ) != 1 )
    1186     {
    1187         _printf("\n[FAT ERROR] The number of FAT copies in FAT region must be 1\n");
    1188         _exit();
    1189     }
    1190     if( (_read_entry( BPB_FAT32_FATSZ32, _fat.fat_cache, 1 ) & 0xF) != 0 )
    1191     {
    1192         _printf("\n[FAT ERROR] The FAT region must be multiple of 32 sectors\n");
    1193         _exit();
    1194     }
    1195     if( _read_entry( BPB_FAT32_ROOTCLUS, _fat.fat_cache, 1 ) != 2 )
    1196     {
    1197         _printf("\n[FAT ERROR] The first cluster index must be 2\n");
    1198         _exit();
    1199     }
    1200     // FS Info always in sector 1
    1201     _fat.fs_info_lba         = _read_entry( BPB_FAT32_FSINFO, _fat.fat_cache, 1 );
    1202 
    1203     // initialise fat descriptor from VBR
    1204     _fat.sectors_per_cluster = _read_entry( BPB_SECPERCLUS, _fat.fat_cache, 1 );
    1205     _fat.sector_size         = _read_entry( BPB_BYTSPERSEC, _fat.fat_cache, 1 );
    1206     _fat.cluster_size        = _fat.sectors_per_cluster * 512;
    1207     _fat.fat_sectors         = _read_entry( BPB_FAT32_FATSZ32, _fat.fat_cache, 1 );
    1208     _fat.fat_lba             = _read_entry( BPB_RSVDSECCNT, _fat.fat_cache, 1 );
    1209     _fat.data_lba            = _fat.fat_lba + _fat.fat_sectors;
    1210     _fat.initialised         = FAT_INITIALISED;
    1211 
    1212     // initalise the lock protecting the FAT
    1213     _spin_lock_init( &_fat.fat_lock );
    1214 
    1215     // initialise file descriptor array
    1216     unsigned int   n;
    1217     for( n = 0 ; n < GIET_OPEN_FILES_MAX ; n++ ) _fat.fd[n].used = 0;
     3135_printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] enters for file <%s> "
     3136        " / bytes = %x / offset = %x\n"
     3137        "first_cluster_id = %x / first_byte_to_move = %x"
     3138        " / last_cluster_id = %x / last_byte_to_move = %x\n",
     3139        x , y , p , inode->name , count , seek ,
     3140        first_cluster_id , first_byte_to_move , last_cluster_id , last_byte_to_move );
     3141#endif
     3142
     3143    // loop on all cluster covering the requested transfer
     3144    unsigned int cluster_id;
     3145    unsigned int done = 0;
     3146    for ( cluster_id = first_cluster_id ; cluster_id <= last_cluster_id ; cluster_id++ )
     3147    {
     3148        // get pointer on the cluster_id buffer in cache
     3149        unsigned char*     cbuf;
     3150        fat_cache_desc_t*  pdesc;
     3151        if ( _get_buffer_from_cache( inode,
     3152                                     cluster_id,
     3153                                     &pdesc ) )
     3154        {
     3155            _spin_lock_release( &_fat.fat_lock );
     3156            _printf("\n[FAT ERROR] in _fat_read() : cannot load file <%s>\n",
     3157                    inode->name );
     3158            return -3;
     3159        }
     3160        cbuf = pdesc->buffer;
    12183161
    12193162#if GIET_DEBUG_FAT
    12203163if ( _get_proctime() > GIET_DEBUG_FAT )
    1221 _printf("\n[DEBUG FAT] _fat_init() : FS_INFO Sector = %x\n", _fat.fs_info_lba );
    1222 #endif
    1223 
    1224     // load FS_INFO into fat cache
    1225     if ( _fat_ioc_access( use_irq,
    1226                           1,                  // read
    1227                           _fat.fs_info_lba,   
    1228                           (unsigned int)_fat.fat_cache,
    1229                           1 ) )               // one sector
    1230     {
    1231         _printf("\n[FAT ERROR] in _fat_init() cannot load FS_INFO Sector\n");
    1232         _exit();
    1233     }
    1234     _fat.cache_lba = _fat.fs_info_lba;
    1235 
    1236     _fat.number_free_cluster    = _read_entry( FS_FREE_CLUSTER     , _fat.fat_cache, 1);
    1237     _fat.last_cluster_allocated = _read_entry( FS_FREE_CLUSTER_HINT, _fat.fat_cache, 1);
     3164_printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] moves cluster_id %d from Cache-File <%s>\n",
     3165        x , y , p , cluster_id, inode->name );
     3166#endif
     3167
     3168        // compute memcpy arguments
     3169        unsigned char*  source;
     3170        unsigned int    nbytes;
     3171        unsigned char*  dest = (unsigned char*)buffer + done;
     3172        if ( (cluster_id == first_cluster_id) && (cluster_id == last_cluster_id) )
     3173        {
     3174            source = cbuf + first_byte_to_move;
     3175            nbytes = last_byte_to_move - first_byte_to_move + 1;
     3176        }
     3177        else if ( cluster_id == first_cluster_id )
     3178        {
     3179            source = cbuf + first_byte_to_move;
     3180            nbytes = 4096 - first_byte_to_move;
     3181        }
     3182        else if ( cluster_id == last_cluster_id )
     3183        {
     3184            source = cbuf;
     3185            nbytes = last_byte_to_move + 1;
     3186        }
     3187        else  // not first / not last
     3188        {
     3189            source = cbuf;
     3190            nbytes = 4096;
     3191        }
     3192
     3193        // move data
     3194        memcpy( dest , source , nbytes );
     3195        done = done + nbytes;
     3196    }
    12383197
    12393198#if GIET_DEBUG_FAT
    12403199if ( _get_proctime() > GIET_DEBUG_FAT )
    1241 _fat_print();
    1242 _printf("\n[DEBUG FAT] P[%d,%d,%d] exit _fat_init()\n", x,y,p );
    1243 #endif
    1244 
    1245     return 0;
    1246 }  // end _fat_init()
    1247 
    1248 ///////////////////////////////////////////////////////////////////////////////
    1249 // This function checks that the kernel FAT structure has been initialised.
    1250 // It searches a file identified by the "pathname" argument.
    1251 // It starts from root (cluster 2) to scan successively each subdirectory.
    1252 // When the file is not found, but the path is found, and "creat" is set,
    1253 // a new file is created and introduced in the directory.
    1254 // Finally, it sets a new open file in the file descriptors array.
    1255 // The same file can be open several times by differents tasks.
    1256 ///////////////////////////////////////////////////////////////////////////////
    1257 // Returns file descriptor index if success, returns -1 if error.
    1258 ///////////////////////////////////////////////////////////////////////////////
    1259 int _fat_open( unsigned int use_irq,       // use descheduling mode if possible
    1260                char*        pathname,
    1261                unsigned int creat )
    1262 {
    1263     char                 name[256];        // buffer for one name in pathname
    1264     unsigned int         nb_read;              // number of characters written in name[]
    1265     unsigned int         cluster;          // current cluster index when scanning FAT
    1266     unsigned int         dir_cluster;      // previous cluster index when scanning FAT
    1267     unsigned int         fd_id;            // index when scanning file descriptors array
    1268     unsigned int         file_size = 0;    // number of bytes
    1269     unsigned int         last_name = 0;    // directory containing file name is reached
    1270     unsigned int         lba       = 0;    // lba of dir_entry for this file
    1271    
     3200_printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] loaded file <%s> from Cache-File\n",
     3201        x , y , p , inode->name );
     3202#endif
     3203
     3204    // update seek
     3205    _fat.fd[fd_id].seek += done;
     3206
     3207    // release lock
     3208    _spin_lock_release( &_fat.fat_lock );
     3209
     3210    return done;
     3211} // end _fat_read()
     3212
     3213
     3214
     3215
     3216/////////////////////////////////////////////////////////////////////////////////
     3217// The following function implements the "giet_fat_write()" system call.
     3218// It transfers "count" bytes to the fat_cache associated to the file
     3219// identified by "fd_id", from the user "buffer", using the current file offset.
     3220// It has the same semantic as the UNIX "write()" function.
     3221// It increases the file size and allocate new clusters if (count + offset)
     3222// is larger than the current file size. Then it loads and updates all
     3223// involved clusters in the cache.
     3224/////////////////////////////////////////////////////////////////////////////////
     3225// Returns number of bytes actually written if success.
     3226// Returns a negative value if error:
     3227//   -1 :  "FAT not initialised"
     3228//   -2 :  "Illegal file descriptor"
     3229//   -3 :  "File not open"
     3230//   -4 :  "File not writable"
     3231//   -5 :  "No free clusters"
     3232//   -6 :  "Cannot update parent directory entry"
     3233//   -7 :  "Cannot access File-Cache"
     3234/////////////////////////////////////////////////////////////////////////////////
     3235int _fat_write( unsigned int fd_id,    // file descriptor index
     3236                void*        buffer,   // source buffer
     3237                unsigned int count )   // number of bytes to write
     3238{
     3239    // checking FAT initialised
     3240    if( _fat.initialised != FAT_INITIALISED )
     3241    {
     3242        _printf("\n[FAT ERROR] in _fat_write() : FAT not initialised\n");
     3243        return -1;
     3244    }
     3245
     3246    // takes lock
     3247    _spin_lock_acquire( &_fat.fat_lock );
     3248           
     3249    // check fd_id overflow
     3250    if ( fd_id >= GIET_OPEN_FILES_MAX )
     3251    {
     3252        _spin_lock_release( &_fat.fat_lock );
     3253        _printf("\n[FAT ERROR] in _fat_write() : illegal file descriptor\n");
     3254        return -2;
     3255    }
     3256
     3257    // check file open
     3258    if ( _fat.fd[fd_id].allocated == 0 )
     3259    {
     3260        _spin_lock_release( &_fat.fat_lock );
     3261        _printf("\n[FAT ERROR] in _fat_write() : file not open\n" );
     3262        return -3;
     3263    }
     3264
     3265    // check file writable
     3266    if ( _fat.fd[fd_id].read_only )
     3267    {
     3268        _spin_lock_release( &_fat.fat_lock );
     3269        _printf("\n[FAT ERROR] in _fat_write() : file <%s> is read-only\n",
     3270                _fat.fd[fd_id].inode->name );
     3271        return -4;
     3272    }
     3273
     3274    // get file inode pointer and seek
     3275    fat_inode_t* inode  = _fat.fd[fd_id].inode;
     3276    unsigned int seek   = _fat.fd[fd_id].seek;
     3277
    12723278#if GIET_DEBUG_FAT
    12733279unsigned int procid  = _get_procid();
     
    12763282unsigned int p       = procid & ((1<<P_WIDTH)-1);
    12773283if ( _get_proctime() > GIET_DEBUG_FAT )
    1278 _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] enters for path %s\n",
    1279         x, y, p, pathname );
    1280 #endif
    1281 
    1282     // checking creat argument
    1283     if ( creat )
    1284     {
    1285         _printf("\n[FAT ERROR] in _fat_open() : create not supported yet\n");
    1286         return -1;
    1287     }
    1288 
     3284_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] enters for file <%s> "
     3285        " / bytes = %x / seek = %x\n",
     3286        x , y , p , inode->name , count , seek );
     3287#endif
     3288
     3289    // chek if file size must be incremented
     3290    // and allocate new clusters from FAT if required
     3291    unsigned int old_size = inode->size;
     3292    unsigned int new_size = seek + count;
     3293    if ( new_size > old_size )
     3294    {
     3295        // update size in inode
     3296        inode->size = new_size;
     3297 
     3298        // compute current and required numbers of clusters
     3299        unsigned old_clusters = old_size >> 12;
     3300        if ( old_size & 0xFFF ) old_clusters++;
     3301
     3302        unsigned new_clusters = new_size >> 12;
     3303        if ( new_size & 0xFFF ) new_clusters++;
     3304
     3305        // allocate new clusters from FAT if required
     3306        if ( new_clusters > old_clusters )
     3307        {
     3308
     3309#if GIET_DEBUG_FAT
     3310if ( _get_proctime() > GIET_DEBUG_FAT )
     3311_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] allocates new clusters for file <%s>"
     3312        " / current = %d / required = %d\n",
     3313        x , y , p , inode->name , old_clusters , new_clusters );
     3314#endif
     3315            // allocate missing clusters
     3316            if ( _clusters_allocate( inode,
     3317                                     old_clusters,
     3318                                     new_clusters - old_clusters ) )
     3319            {
     3320                _spin_lock_release( &_fat.fat_lock );
     3321                _printf("\n[FAT ERROR] in _fat_write() : no free clusters"
     3322                        " for file <%s>\n", _fat.fd[fd_id].inode->name );
     3323                return -5;
     3324            }
     3325        }
     3326         
     3327        // update parent directory entry (size an cluster index)
     3328        if ( _update_dir_entry( inode ) )
     3329        {
     3330            _spin_lock_release( &_fat.fat_lock );
     3331            _printf("\n[FAT ERROR] in _fat_write() : cannot update parent directory entry"
     3332                    " for file <%s>\n", _fat.fd[fd_id].inode->name );
     3333            return -6;
     3334        }
     3335           
     3336
     3337#if GIET_DEBUG_FAT
     3338if ( _get_proctime() > GIET_DEBUG_FAT )
     3339_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] updates size for file <%s> / size = %x\n",
     3340        x , y , p , inode->name , (new_size - old_size) );
     3341#endif
     3342
     3343    }
     3344
     3345    // compute first_cluster_id and first_byte_to_move
     3346    unsigned int first_cluster_id   = seek >> 12;
     3347    unsigned int first_byte_to_move = seek & 0xFFF;   
     3348
     3349    // compute last_cluster and last_byte_to_move
     3350    unsigned int last_cluster_id   = (seek + count - 1) >> 12;   
     3351    unsigned int last_byte_to_move = (seek + count - 1) & 0xFFF;
     3352
     3353#if GIET_DEBUG_FAT
     3354if ( _get_proctime() > GIET_DEBUG_FAT )
     3355_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] starts loop on clusters for file <%s>\n"
     3356        "  first_cluster_id = %d / first_byte_to_move = %x"
     3357        " / last_cluster_id = %d / last_byte_to_move = %x\n",
     3358        x , y , p , inode->name ,
     3359        first_cluster_id , first_byte_to_move , last_cluster_id , last_byte_to_move );
     3360#endif
     3361
     3362    // loop on all clusters covering the requested transfer
     3363    unsigned int cluster_id;
     3364    unsigned int done = 0;
     3365    for ( cluster_id = first_cluster_id ; cluster_id <= last_cluster_id ; cluster_id++ )
     3366    {
     3367        // get pointer on one 4K buffer in File-Cache
     3368        unsigned char*     cbuf;
     3369        fat_cache_desc_t*  pdesc;
     3370        if ( _get_buffer_from_cache( inode,   
     3371                                     cluster_id, 
     3372                                     &pdesc ) )   
     3373        {
     3374            _spin_lock_release( &_fat.fat_lock );
     3375            _printf("\n[FAT ERROR] in _fat_write() : cannot load file <%s>\n",
     3376                    inode->name );
     3377            return -7;
     3378        }
     3379       
     3380        cbuf         = pdesc->buffer;
     3381        pdesc->dirty = 1;
     3382   
     3383#if GIET_DEBUG_FAT
     3384if ( _get_proctime() > GIET_DEBUG_FAT )
     3385_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] move cluster_id %d to Cache-file <%s>\n",
     3386        x , y , p , cluster_id, inode->name );
     3387#endif
     3388
     3389        // compute memcpy arguments
     3390        unsigned char* source = (unsigned char*)buffer + done;
     3391        unsigned char* dest;
     3392        unsigned int   nbytes;
     3393        if ( (cluster_id == first_cluster_id) && (cluster_id == last_cluster_id) )
     3394        {
     3395            dest   = cbuf + first_byte_to_move;
     3396            nbytes = last_byte_to_move - first_byte_to_move + 1;
     3397        }
     3398        else if ( cluster_id == first_cluster_id )
     3399        {
     3400            dest   = cbuf + first_byte_to_move;
     3401            nbytes = 4096 - first_byte_to_move;
     3402        }
     3403        else if ( cluster_id == last_cluster_id )
     3404        {
     3405            dest   = cbuf;
     3406            nbytes = last_byte_to_move + 1;
     3407        }
     3408        else
     3409        {
     3410            dest   = cbuf;
     3411            nbytes = 4096;
     3412        }
     3413
     3414        //move date
     3415        memcpy( dest , source , nbytes );
     3416        done = done + nbytes;
     3417
     3418    } // end for clusters
     3419
     3420    // update seek
     3421    _fat.fd[fd_id].seek += done;
     3422
     3423#if GIET_DEBUG_FAT
     3424if ( _get_proctime() > GIET_DEBUG_FAT )
     3425_printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] store file <%s> into Cache-File\n",
     3426        x , y , p , inode->name );
     3427#endif
     3428
     3429    // release lock
     3430    _spin_lock_release( &_fat.fat_lock );
     3431
     3432    return done;
     3433} // end _fat_write()
     3434
     3435
     3436
     3437/////////////////////////////////////////////////////////////////////////////////
     3438// The following function implements the "giet_fat_lseek()" system call.
     3439// It repositions the seek in the file descriptor "fd_id", according to
     3440// the "seek" and "whence" arguments.
     3441// It has the same semantic as the UNIX lseek() function.
     3442// Accepted values for whence are SEEK_SET and SEEK_CUR.
     3443/////////////////////////////////////////////////////////////////////////////////
     3444// Returns new seek value (bytes) if success.
     3445// Returns negative value if error:
     3446//   -1  : "FAT not initialised"
     3447//   -2  : "Illegal file descriptor"
     3448//   -3  : "File not open"
     3449//   -4  : "Illegal whence argument"
     3450/////////////////////////////////////////////////////////////////////////////////
     3451int _fat_lseek( unsigned int fd_id,
     3452                unsigned int seek,
     3453                unsigned int whence )
     3454{
    12893455    // checking FAT initialised
    12903456    if( _fat.initialised != FAT_INITIALISED )
    12913457    {
    1292         _printf("\n[FAT ERROR] in _fat_open() : FAT not initialised\n");
     3458        _printf("\n[FAT ERROR] in _fat_lseek() : FAT not initialised\n");
    12933459        return -1;
    12943460    }
    1295     // takes the FAT lock for exclusive access
     3461
     3462    // check fd_id overflow
     3463    if ( fd_id >= GIET_OPEN_FILES_MAX )
     3464    {
     3465        _printf("\n[FAT ERROR] in _fat_lseek() : illegal file descriptor\n");
     3466        return -2;
     3467    }
     3468
     3469    // takes lock
    12963470    _spin_lock_acquire( &_fat.fat_lock );
    12973471
    1298 #if GIET_DEBUG_FAT
    1299 if ( _get_proctime() > GIET_DEBUG_FAT )
    1300 _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] takes the FAT lock\n",
    1301         x, y, p );
    1302 #endif
    1303  
    1304     // Scan the directories, starting from the root directory (cluster 2)
    1305     // - The get_name_from_path() function extracts (successively)
    1306     //   each directory name from the pathname, and store it in name[] buffer
    1307     // - The _scan_directory() function scan one (or several) cluster(s) containing
    1308     //   a directory looking for name[], and return the cluster index
    1309     //   corresponding to the directory/file found.
    1310     nb_read     = 0;
    1311     cluster     = 2;
    1312     last_name   = 0;
    1313     while ( get_name_from_path( pathname, name, &nb_read) )
    1314     {
    1315 
    1316 #if GIET_DEBUG_FAT
    1317 if ( _get_proctime() > GIET_DEBUG_FAT )
    1318 _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] search file/dir %s\n",
    1319         x, y, p, name );
    1320 #endif
    1321 
    1322         // test if we reach the last name (file name)
    1323         if( pathname[nb_read] == 0 ) 
    1324         {
    1325             last_name   = 1;
    1326             dir_cluster = cluster;   // this is the lowest directory
    1327         }
    1328 
    1329         // scan current directory
    1330         cluster = _scan_directory( use_irq , cluster , name , &file_size , &lba );
    1331 
    1332         if( cluster == END_OF_CHAIN_CLUSTER && last_name && creat )
    1333         {
    1334             cluster = _fat_create( name, 1, dir_cluster );
    1335         }
    1336         else if ( cluster == END_OF_CHAIN_CLUSTER )
    1337         {
    1338             _printf("\n[FAT ERROR] in _fat_open() cannot found %s\n", name );
    1339             _spin_lock_release( &_fat.fat_lock );
    1340             return -1;
    1341         }
    1342     }
    1343 
    1344 #if GIET_DEBUG_FAT
    1345 if ( _get_proctime() > GIET_DEBUG_FAT )
    1346 _printf("\n[DEBUG FAT] P[%d,%d,%d] in _fat_open() : cluster for %s = %x\n",
    1347        x, y, p, pathname, cluster );
    1348 #endif
    1349 
    1350     // check the next value for cluster index found
    1351     unsigned next = _get_next_cluster( use_irq , cluster );
    1352 
    1353     if ( (next != BAD_CLUSTER) && (next != FREE_CLUSTER) )
    1354     {
    1355         // Search an empty slot scanning open file descriptors array
    1356         fd_id = 0;
    1357         while ( _fat.fd[fd_id].used != 0 && fd_id < GIET_OPEN_FILES_MAX )
    1358         {
    1359             fd_id++;
    1360         }
    1361 
    1362         // set file descriptor if found empty slot
    1363         if ( fd_id < GIET_OPEN_FILES_MAX )
    1364         {
    1365             _fat.fd[fd_id].used          = 1;
    1366             _fat.fd[fd_id].first_cluster = cluster;
    1367             _fat.fd[fd_id].file_size     = file_size;
    1368             _fat.fd[fd_id].lba_dir_entry = lba;
    1369             _strcpy( _fat.fd[fd_id].name, pathname );
    1370 
    1371 #if GIET_DEBUG_FAT
    1372 if ( _get_proctime() > GIET_DEBUG_FAT )
    1373 _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] exit : fd = %d for file %s\n",
    1374         x, y, p, fd_id, pathname );
    1375 #endif
    1376 
    1377             // release FAT lock
    1378             _spin_lock_release( &_fat.fat_lock );
    1379 
    1380             return fd_id;
    1381         }
    1382         else
    1383         {
    1384             _printf("\n[FAT ERROR] in _fat_open() for file %s : fd array full\n",
    1385                     pathname );
    1386             _spin_lock_release( &_fat.fat_lock );
    1387             return -1;
    1388         }
    1389     }
     3472    // check file open
     3473    if ( _fat.fd[fd_id].allocated == 0 )
     3474    {
     3475        _spin_lock_release( &_fat.fat_lock );
     3476        _printf("\n[FAT ERROR] in _fat_lseek() : file not open\n");
     3477        return -3;
     3478    }
     3479
     3480    unsigned int  new_seek;
     3481
     3482    // compute new seek
     3483    if      ( whence == SEEK_CUR ) new_seek = _fat.fd[fd_id].seek + seek;
     3484    else if ( whence == SEEK_SET ) new_seek = seek;
    13903485    else
    13913486    {
    1392         _printf("\n[FAT ERROR] in _fat_open() for file %s : bad cluster\n",
    1393                 pathname );
    13943487        _spin_lock_release( &_fat.fat_lock );
    1395         return -1;
    1396     }
    1397 } // end _fat_open()
    1398 
    1399 ///////////////////////////////////////////////////////////////////////////////
    1400 // For an open file, identified by the file descriptor index, transfer
    1401 // an integer number of sectors from block device to a memory buffer.
    1402 // If the number of requested sectors exceeds the file size, it is reduced.
    1403 ///////////////////////////////////////////////////////////////////////////////
    1404 // Returns number of sectors transfered if success, < 0 if error.
    1405 ///////////////////////////////////////////////////////////////////////////////
    1406 int _fat_read( unsigned int use_irq,    // use descheduling mode if possible
    1407                unsigned int fd_id,      // file descriptor
    1408                void*        buffer,     // target buffer base address
    1409                unsigned int count,      // number of sector to read
    1410                unsigned int offset )    // nuber of sectors to skip in file
    1411 {
    1412     unsigned int spc = _fat.sectors_per_cluster;
    1413 
    1414     unsigned int file_size;         // number of bytes in file
    1415     unsigned int file_sectors;      // number of sectors in file
    1416     unsigned int total_sectors;     // actual number of sectors to be transfered
    1417     unsigned int cluster;           // cluster index
    1418     unsigned int clusters_to_skip;  // number of clusters to skip because offset
    1419     unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
    1420 
    1421     // arguments checking
    1422     if ( fd_id >= GIET_OPEN_FILES_MAX )
    1423     {
    1424         _printf("\n[FAT ERROR] in _fat_read() : illegal file descriptor index\n");
    1425         return -1;
    1426     }
    1427     if ( _fat.fd[fd_id].used != 1 )
    1428     {
    1429         _printf("\n[FAT ERROR] in _fat_read() : file not open\n");
    1430         return -1;
    1431     }
    1432     if ( ((unsigned int)buffer & 0x1FF) != 0 )
    1433     {
    1434         _printf("\n[FAT ERROR] in _fat_read() : memory buffer not sector aligned\n");
    1435         return -1;
    1436     }
    1437 
    1438     // compute file size as a number of sectors
    1439     file_size    = _fat.fd[fd_id].file_size;
    1440     if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
    1441     else                     file_sectors = (file_size >> 9);
    1442 
    1443     if ( offset >= file_sectors )
    1444     {
    1445         _printf("\n[FAT ERROR] offset larger than number of sectors\n");
    1446         return -1;
    1447     }
    1448 
    1449     // compute total number of sectors to read
    1450     if ( file_sectors < (offset + count) ) total_sectors = file_sectors - offset;
    1451     else                                   total_sectors = count;
    1452 
    1453     // compute clusters and sectors to be skipped
    1454     clusters_to_skip = offset / spc;
    1455     sectors_to_skip  = offset % spc;
    1456    
    1457     // get first cluster index
    1458     cluster = _fat.fd[fd_id].first_cluster;
     3488        _printf("\n[FAT ERROR] in _fat_user_lseek() : illegal whence valuel\n");
     3489        return -4;
     3490    }
     3491
     3492    // update file descriptor offset
     3493    _fat.fd[fd_id].seek = new_seek;
    14593494
    14603495#if GIET_DEBUG_FAT
     
    14643499unsigned int p       = procid & ((1<<P_WIDTH)-1);
    14653500if ( _get_proctime() > GIET_DEBUG_FAT )
    1466 _printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] enters for file %s\n"
    1467         " - buffer vbase     = %x\n"
    1468         " - skipped sectors  = %x\n"
    1469         " - read sectors     = %x\n"
    1470         " - first cluster    = %x\n"
    1471         " - skipped clusters = %x\n",
    1472         x, y, p, _fat.fd[fd_id].name, (unsigned int)buffer,
    1473         offset, count, cluster, clusters_to_skip );
    1474 #endif
    1475 
    1476     // compute index of first cluster to be loaded
    1477     while ( clusters_to_skip )
    1478     {
    1479         cluster = _get_next_cluster( use_irq , cluster );
    1480         clusters_to_skip--;
    1481     }
    1482 
    1483     // variables used in the loop on clusters
    1484     int             todo_sectors;   // number of sectors still to be loaded
    1485     unsigned int    lba;            // first sector index on device
    1486     unsigned int    iter_sectors;   // number of sectors to load in iteration
    1487     unsigned int    dst;            // pointer on target buffer
    1488 
    1489     // initialize these variables for the first iteration
    1490     todo_sectors  = total_sectors;
    1491     dst           = (unsigned int)buffer;
    1492     lba           = cluster_to_lba(cluster) + sectors_to_skip;
    1493     if( total_sectors < (spc - sectors_to_skip) ) iter_sectors = total_sectors;
    1494     else                                          iter_sectors = spc - sectors_to_skip;
    1495 
    1496     // loop on the clusters: one IOC access per cluster
    1497     while ( todo_sectors > 0 )
    1498     {
    1499 
    1500 #if GIET_DEBUG_FAT
    1501 if ( _get_proctime() > GIET_DEBUG_FAT )
    1502 _printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] makes an IOC read\n"
    1503         "  cluster = %x / buffer = %x / lba = %x / sectors = %d\n",
    1504         x, y, p, cluster, dst, lba, iter_sectors );
    1505 #endif
    1506 
    1507         if( _fat_ioc_access( use_irq,
    1508                              1,                 // read
    1509                              lba,
    1510                              dst,               // buffer address
    1511                              iter_sectors ) )   // number of sectors
    1512         {
    1513             _printf("\n[FAT ERROR] in _fat_read() cannot load block %x", lba );
    1514             return -1;
    1515         }
    1516          
    1517         // update variables for next iteration
    1518         cluster      = _get_next_cluster( use_irq , cluster );
    1519         todo_sectors = todo_sectors - iter_sectors;
    1520         dst          = dst + (iter_sectors << 9);
    1521         lba          = cluster_to_lba(cluster);
    1522         if ( todo_sectors > spc ) iter_sectors = spc;
    1523         else                      iter_sectors = todo_sectors;
    1524     }
    1525          
    1526     // returns number of sectors actually transfered
    1527     return total_sectors;
    1528 
    1529 }  // end _fat_read()
    1530 
    1531 ///////////////////////////////////////////////////////////////////////////////
    1532 // For an open file, identified by the file descriptor index, transfer
    1533 // an integer number of sectors from a memory buffer to block device.
    1534 // Allocate new clusters if the offset+count larger than current file size,
    1535 // but the offset should be smaller than the current file size...
    1536 ///////////////////////////////////////////////////////////////////////////////
    1537 // Returns number of sectors written if success, < 0 if error.
    1538 ///////////////////////////////////////////////////////////////////////////////
    1539 int _fat_write( unsigned int use_irq,    // use descheduling mode if possible
    1540                 unsigned int fd_id,      // file descriptor
    1541                 void*        buffer,     // target buffer base address
    1542                 unsigned int count,      // number of sector to write
    1543                 unsigned int offset )    // nuber of sectors to skip in file
    1544 {
    1545 
    1546     unsigned int spc = _fat.sectors_per_cluster;
    1547 
    1548     unsigned int file_size;         // number of bytes in file
    1549     unsigned int file_sectors;      // number of sectors in file
    1550     unsigned int cluster;           // cluster index
    1551     unsigned int clusters_to_skip;  // number of clusters to skip because offset
    1552     unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
    1553     unsigned int allocate;          // need allocate or not
    1554     unsigned int current_cluster;   // number of cluster allocated to the file
    1555     unsigned int required_cluster;  // number of cluster needed for the write
    1556 
    1557     // compute file size as a number of sectors
    1558     file_size    = _fat.fd[fd_id].file_size;
    1559     if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
    1560     else                     file_sectors = (file_size >> 9);
    1561 
    1562     // Compute the number of clusters occupied by the file
    1563     current_cluster = file_sectors / spc;
    1564 
    1565     // Compute the number of clusters that will occupy the file (after fat_write)
    1566     required_cluster = (count + offset) / spc;
    1567 
    1568     // Check if we need to allocate new cluster(s) for the file 
    1569     allocate = ( required_cluster > current_cluster );
     3501_printf("\n[DEBUG FAT] _fat_lseek() : P[%d,%d,%d] set seek = %x for file <%s>\n",
     3502        x , y , p , new_seek , _fat.fd[fd_id].inode->name );
     3503#endif
     3504
     3505    // release lock
     3506    _spin_lock_release( &_fat.fat_lock );
     3507
     3508    return new_seek;
     3509}  // end _fat_lseek()
     3510
     3511
     3512
     3513/////////////////////////////////////////////////////////////////////////////////
     3514// The following function implements the giet_fat_remove() system call.
     3515// It deletes the file/directory identified by the "pathname" argument from
     3516// the file system, if the remove condition is fulfilled (directory empty,
     3517// or file not referenced).
     3518// All clusters allocated in the block device DATA region are released.
     3519// The FAT region is updated on the block device.
     3520// The Inode-Tree is updated.
     3521// The associated File_Cache is released.
     3522// The Fat_Cache is updated.
     3523/////////////////////////////////////////////////////////////////////////////////
     3524// Returns 0 if success.
     3525// Returns negative value if error
     3526//   -1  : "FAT not initialised"
     3527//   -2  : "File/Directory not found"
     3528//   -3  : "Name too long in path"
     3529//   -4  : "Has the wrong type"
     3530//   -5  : "File still open"
     3531//   -6  : "Cannot scan directory"
     3532//   -7  : "Directory not empty"
     3533//   -8  : "Cannot remove file/dir from FS"
     3534/////////////////////////////////////////////////////////////////////////////////
     3535int _fat_remove( char*        pathname,
     3536                 unsigned int should_be_dir )
     3537{
     3538    fat_inode_t*  inode;            // searched file inode pointer
    15703539
    15713540#if GIET_DEBUG_FAT
     
    15753544unsigned int p       = procid & ((1<<P_WIDTH)-1);
    15763545if ( _get_proctime() > GIET_DEBUG_FAT )
    1577 _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] enters for file %s\n"
    1578         " - buffer vbase    = %x\n"
    1579         " - skipped sectors = %x\n"
    1580         " - write sectors   = %x\n"
    1581         " - file sectors    = %x\n"
    1582         " - need_allocate   = %d\n",
    1583         x, y, p, _fat.fd[fd_id].name, (unsigned int)buffer,
    1584         offset, count, file_sectors, allocate );
    1585 #endif
    1586 
    1587     // arguments checking
    1588     if ( fd_id >= GIET_OPEN_FILES_MAX )
    1589     {
    1590         _printf("\n[FAT ERROR] in _fat_write() : illegal file descriptor index\n");
     3546_printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] enters for path <%s>\n",
     3547        x, y, p, pathname );
     3548#endif
     3549
     3550    // checking FAT initialised
     3551    if( _fat.initialised != FAT_INITIALISED )
     3552    {
     3553        _printf("\n[FAT ERROR] in _fat_remove() : FAT not initialised\n");
    15913554        return -1;
    15923555    }
    1593     if ( _fat.fd[fd_id].used != 1 )
    1594     {
    1595         _printf("\n[FAT ERROR] in _fat_write() : file not open\n");
     3556
     3557    // take the lock
     3558    _spin_lock_acquire( &_fat.fat_lock );
     3559
     3560    // get searched file inode
     3561    unsigned int code = _get_inode_from_path( pathname , &inode );
     3562
     3563#if GIET_DEBUG_FAT
     3564if ( _get_proctime() > GIET_DEBUG_FAT )
     3565_printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] found inode %x for <%s> / code = %d\n",
     3566        x , y , p , (unsigned int)inode , pathname , code );
     3567#endif
     3568
     3569    if ( (code == 1) || (code == 2) )
     3570    {
     3571        _spin_lock_release( &_fat.fat_lock );
     3572        _printf("\n[FAT ERROR] in _fat_remove() : file <%s> not found\n",
     3573                pathname );
     3574        return -2;
     3575    }
     3576    else if ( code == 3 )
     3577    {
     3578        _spin_lock_release( &_fat.fat_lock );
     3579        _printf("\n[FAT ERROR] in _fat_remove() : name too long in <%s>\n",
     3580                pathname );
     3581        return -3;
     3582    }
     3583
     3584    // check inode type
     3585    if ( (inode->is_dir != 0) && (should_be_dir == 0) )
     3586    {
     3587        _spin_lock_release( &_fat.fat_lock );
     3588        _printf("\n[FAT ERROR] in _fat_remove() : <%s> is a directory\n",
     3589                pathname );
     3590        return -4;
     3591    }
     3592    if ( (inode->is_dir == 0) && (should_be_dir != 0) )
     3593    {
     3594        _spin_lock_release( &_fat.fat_lock );
     3595        _printf("\n[FAT ERROR] in _fat_remove() : <%s> is not a directory\n",
     3596                pathname );
     3597        return -4;
     3598    }
     3599
     3600#if GIET_DEBUG_FAT
     3601if ( _get_proctime() > GIET_DEBUG_FAT )
     3602_printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] checked inode type for <%s>\n",
     3603        x , y , p , pathname );
     3604#endif
     3605   
     3606    // check references count for a file
     3607    if ( (inode->is_dir == 0) && (inode->count != 0) )
     3608    {
     3609        _spin_lock_release( &_fat.fat_lock );
     3610        _printf("\n[FAT ERROR] in _fat_remove() : file <%s> still referenced\n",
     3611                pathname );
     3612        return -5;
     3613    }
     3614
     3615    //  check empty for a directory
     3616    if ( inode->is_dir )
     3617    {
     3618        unsigned int entries;
     3619        if ( _get_nb_entries( inode , &entries ) )
     3620        {
     3621            _spin_lock_release( &_fat.fat_lock );
     3622            _printf("\n[FAT ERROR] in _fat_remove() : cannot scan directory <%s>\n",
     3623                    pathname );
     3624            return -6;
     3625        }
     3626        else if ( entries > 2 )
     3627        {
     3628            _spin_lock_release( &_fat.fat_lock );
     3629            _printf("\n[FAT ERROR] in _fat_remove() : directory <%s> not empty\n",
     3630                    pathname );
     3631            return -7;
     3632        }
     3633    }
     3634
     3635#if GIET_DEBUG_FAT
     3636if ( _get_proctime() > GIET_DEBUG_FAT )
     3637_printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] checked remove condition OK for <%s>\n",
     3638        x , y , p , pathname );
     3639#endif
     3640   
     3641    // remove the file or directory from the file system
     3642    if ( _remove_node_from_fs( inode ) )
     3643    {
     3644        _spin_lock_release( &_fat.fat_lock );
     3645        _printf("\n[FAT ERROR] in _fat_remove() : cannot remove <%s> from FS\n",
     3646                pathname );
     3647        return -8;
     3648    }
     3649
     3650    // release lock and return success
     3651    _spin_lock_release( &_fat.fat_lock );
     3652
     3653#if GIET_DEBUG_FAT
     3654if ( _get_proctime() > GIET_DEBUG_FAT )
     3655_printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] removed  <%s> from FS\n",
     3656        x, y, p, pathname );
     3657#endif
     3658   
     3659    return 0;
     3660       
     3661}  // end _fat_remove()
     3662
     3663
     3664
     3665
     3666
     3667/////////////////////////////////////////////////////////////////////////////////
     3668// This function implements the giet_fat_rename() system call.
     3669// It moves an existing file or directory from one node (defined by "old_path"
     3670// argument) to another node (defined by "new_path" argument) in the FS tree.
     3671// The type (file/directory) and content are not modified.
     3672// If the new_path file/dir exist, it is removed from the file system, but only 
     3673// if the remove condition is respected (directory empty / file not referenced).
     3674// The removed entry is only removed after the new entry is actually created.
     3675/////////////////////////////////////////////////////////////////////////////////
     3676// Returns 0 if success.
     3677// Returns a negative value if error:
     3678//  -1  : "FAT not initialised"
     3679//  -2  : "old_path not found"
     3680//  -3  : "new_path not found"
     3681//  -4  : "cannot scan to_remove directory"
     3682//  -5  : "to_remove directory not empty"
     3683//  -6  : "to_remove file still referenced"
     3684//  -7  : "cannot add new node to new_parent directory"
     3685//  -8  : "cannot update new_parent directory on device"
     3686//  -9  : "cannot remove old node from old_parent directory"
     3687//  -10 : "cannot update old_parent directory on device"
     3688//  -11 : "cannot remove to_remove node from FS"
     3689/////////////////////////////////////////////////////////////////////////////////
     3690int _fat_rename( char*  old_path,
     3691                 char*  new_path )
     3692{
     3693    fat_inode_t*  inode;        // anonymous inode pointer
     3694    fat_inode_t*  old;          // inode identified by old_path      => to be deleted
     3695    fat_inode_t*  new;          // inode identified by new_path      => to be created
     3696    fat_inode_t*  old_parent;   // parent inode  in old_path         => to be modified
     3697    fat_inode_t*  new_parent;   // parent inode  in new_path         => to be modified
     3698    fat_inode_t*  to_remove;    // previouly identified by new_path  => to be removed
     3699    unsigned int  code;
     3700
     3701#if GIET_DEBUG_FAT
     3702unsigned int procid  = _get_procid();
     3703unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
     3704unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
     3705unsigned int p       = procid & ((1<<P_WIDTH)-1);
     3706if ( _get_proctime() > GIET_DEBUG_FAT )
     3707_printf("\n[DEBUG FAT] _fat_rename() : P[%d,%d,%d] enters to move <%s> to <%s>\n",
     3708        x , y , p , old_path , new_path );
     3709#endif
     3710
     3711    // checking FAT initialised
     3712    if( _fat.initialised != FAT_INITIALISED )
     3713    {
     3714        _printf("\n[FAT ERROR] in _fat_rename() : FAT not initialised\n");
    15963715        return -1;
    15973716    }
    1598     if ( ((unsigned int)buffer & 0x1FF) != 0 )
    1599     {
    1600         _printf("\n[FAT ERROR] in _fat_write() : memory buffer not sector aligned\n");
     3717
     3718    // take the lock
     3719    _spin_lock_acquire( &_fat.fat_lock );
     3720
     3721    // get "old" and "old_parent" inode pointers
     3722    if ( _get_inode_from_path( old_path , &inode ) )
     3723    {
     3724        _spin_lock_release( &_fat.fat_lock );
     3725        _printf("\n[FAT ERROR] in _fat_rename() : <%s> not found\n", old_path );
     3726        return -2;
     3727    }
     3728    else
     3729    {
     3730        old        = inode;
     3731        old_parent = inode->parent;
     3732    }
     3733
     3734    // get "to_removed" and "new_parent" inode pointers
     3735    code = _get_inode_from_path( new_path , &inode );
     3736
     3737    if ( code == 0 )       // new_path inode already exist
     3738    {
     3739        to_remove        = inode;
     3740        new_parent       = inode->parent;   
     3741    }
     3742    else if ( code == 1 )  // to_remove does not exist but parent exist
     3743    {
     3744        to_remove        = NULL;
     3745        new_parent       = inode;
     3746    }
     3747    else                   // parent directory in new_path not found
     3748    {
     3749        _spin_lock_release( &_fat.fat_lock );
     3750        _printf("\n[FAT ERROR] in _fat_rename() : <%s> not found\n", new_path );
     3751        return -3;
     3752    }
     3753
     3754#if GIET_DEBUG_FAT
     3755if ( _get_proctime() > GIET_DEBUG_FAT )
     3756{
     3757if ( to_remove )
     3758_printf("\n[DEBUG FAT] _fat_rename() : old_parent = %s / old = %s / new_parent = %s "
     3759        "/ to_remove = %s\n",
     3760        old_parent->name , old->name , new_parent->name , to_remove->name );
     3761else
     3762_printf("\n[DEBUG FAT] _fat_rename() : old_parent = %s / old = %s / new_parent = %s "
     3763        "/ no remove\n",
     3764        old_parent->name , old->name , new_parent->name );
     3765}
     3766#endif
     3767
     3768    // check remove condition for "to_remove" inode
     3769    if ( to_remove )
     3770    {
     3771        if ( to_remove->is_dir )   // it's a directory
     3772        {
     3773            unsigned int entries;
     3774            if ( _get_nb_entries( to_remove , &entries ) )
     3775            {
     3776                _spin_lock_release( &_fat.fat_lock );
     3777                _printf("\n[FAT ERROR] in _fat_rename() : cannot scan directory <%s>\n",
     3778                        to_remove->name );
     3779                return -4;
     3780            }
     3781            else if ( entries > 2 )
     3782            {
     3783                _spin_lock_release( &_fat.fat_lock );
     3784                _printf("\n[FAT ERROR] in _fat_rename() : directory <%s> not empty\n",
     3785                        to_remove->name );
     3786                return -5;
     3787            }
     3788        }
     3789        else                       // it's a file
     3790        {
     3791            if ( to_remove->count )
     3792            {
     3793                _spin_lock_release( &_fat.fat_lock );
     3794                _printf("\n[FAT ERROR] in _fat_rename() : file <%s> still referenced\n",
     3795                        to_remove->name );
     3796                return -6;
     3797            }
     3798        }
     3799    }
     3800
     3801#if GIET_DEBUG_FAT
     3802if ( _get_proctime() > GIET_DEBUG_FAT )
     3803_printf("\n[FAT DEBUG] _fat_rename() : P[%d,%d,%d] checked remove condition OK\n",
     3804        x , y , p );
     3805#endif
     3806
     3807    // get new last name / error checking already done by _get_inode_from_path()
     3808    char  new_name[32];
     3809    _get_last_name( new_path , new_name );
     3810
     3811    // allocate "new" inode
     3812    new = _allocate_one_inode( new_name,
     3813                               old->is_dir,
     3814                               old->cluster,
     3815                               old->size,
     3816                               0,              // count
     3817                               0,              // dentry
     3818                               0 );            // no cache_allocate
     3819 
     3820    // give the "old" File-Cache to the "new inode
     3821    new->levels = old->levels;
     3822    new->cache  = old->cache;
     3823
     3824    // add "new" to "new_parent" directory File-Cache
     3825    if ( _add_dir_entry( new , new_parent ) )
     3826    {
     3827        _spin_lock_release( &_fat.fat_lock );
     3828        _printf("\n[FAT ERROR] in _fat_rename() : cannot add <%s> into <%s>\n",
     3829                new->name , new_parent->name );
     3830        return -7;
     3831    }
     3832
     3833    // add "new" to "new_parent" directory in Inode-Tree
     3834    _add_inode_in_tree( new , new_parent );
     3835   
     3836    // updates "new_parent" directory on device
     3837    if ( _update_device_from_cache( new_parent->levels,
     3838                                    new_parent->cache,
     3839                                    new_parent->name ) )
     3840    {
     3841        _spin_lock_release( &_fat.fat_lock );
     3842        _printf("\n[FAT ERROR] in _fat_rename() : cannot update <%s> on device\n",
     3843                    new_parent->name );
     3844        return -8;
     3845    }
     3846
     3847    // remove "old" from "old_parent" File-Cache
     3848    if ( _remove_dir_entry( old ) )
     3849    {
     3850        _spin_lock_release( &_fat.fat_lock );
     3851        _printf("\n[FAT ERROR] in _fat_rename() : cannot remove <%s> from <%s>\n",
     3852                old->name , old_parent->name );
     3853        return -9;
     3854    }
     3855 
     3856    // remove "old" inode from Inode-Tree
     3857    _remove_inode_from_tree( old );
     3858
     3859    // updates "old_parent" directory on device
     3860    if ( _update_device_from_cache( old_parent->levels,
     3861                                    old_parent->cache,
     3862                                    old_parent->name ) )
     3863    {
     3864        _spin_lock_release( &_fat.fat_lock );
     3865        _printf("\n[FAT ERROR] in _fat_rename() : cannot update <%s> on device\n",
     3866                    old_parent->name );
     3867        return -10;
     3868    }
     3869
     3870    // remove "to_remove" from File System (if required)
     3871    if ( to_remove )
     3872    {
     3873        if ( _remove_node_from_fs( to_remove ) )
     3874        {
     3875            _spin_lock_release( &_fat.fat_lock );
     3876            _printf("\n[FAT ERROR] in _fat_rename() : cannot remove <%s> from FS\n",
     3877                    to_remove->name );
     3878            return -11;
     3879        }
     3880    }
     3881
     3882    // release lock
     3883    _spin_lock_release( &_fat.fat_lock );
     3884
     3885    return 0;
     3886}  // end _fat_rename()
     3887
     3888
     3889
     3890
     3891/////////////////////////////////////////////////////////////////////////////////
     3892// The following function implements the giet_fat_mkdir() system call.
     3893// It creates in file system the directory specified by the "pathname" argument.
     3894// The Inode-Tree is updated.
     3895// One cluster is allocated to the new directory.
     3896// The associated File-Cache is created.
     3897// The FAT region on block device is updated.
     3898// The DATA region on block device is updated.
     3899/////////////////////////////////////////////////////////////////////////////////
     3900// Returns 0 if success.
     3901// Returns a negative value if error:
     3902//   -1  : "Fat not initialised"
     3903//   -2  : "Path to parent not found"
     3904//   -3  : "One name in path too long"
     3905//   -4  : "Directory already exist"
     3906//   -5  : "No free cluster"
     3907//   -6  : "Cannot update parent directory"
     3908//   -7  : "Cannot update parent DATA region"
     3909//   -8  : "Cannot update FAT region"
     3910//   -9  : "Cannot update FS-INFO"
     3911//   -10 : "Cannot update directory DATA region"
     3912/////////////////////////////////////////////////////////////////////////////////
     3913int _fat_mkdir( char* pathname )
     3914{
     3915    fat_inode_t*         inode;            // anonymous inode pointer
     3916    fat_inode_t*         child;            // searched directory inode pointer
     3917    fat_inode_t*         parent;           // parent directory inode pointer
     3918
     3919#if GIET_DEBUG_FAT
     3920unsigned int procid  = _get_procid();
     3921unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
     3922unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
     3923unsigned int p       = procid & ((1<<P_WIDTH)-1);
     3924if ( _get_proctime() > GIET_DEBUG_FAT )
     3925_printf("\n[DEBUG FAT] _fat_mkdir() : P[%d,%d,%d] enters for path <%s>\n",
     3926        x, y, p, pathname );
     3927#endif
     3928
     3929    // checking FAT initialised
     3930    if( _fat.initialised != FAT_INITIALISED )
     3931    {
     3932        _printf("\n[FAT ERROR] in _fat_mkdir() : FAT not initialised\n");
    16013933        return -1;
    16023934    }
    16033935
    1604     if ( allocate  )
    1605     {
    1606         if ( _fat_allocate( use_irq , fd_id, (required_cluster-current_cluster) ) )
    1607         {
    1608             _printf("\n[FAT ERROR] in _fat_write() : fat_allocate failed\n");
    1609             return -1;
    1610         }
    1611     }
    1612 
    1613     // compute clusters and sectors to be skipped
    1614     clusters_to_skip = offset / spc;
    1615     sectors_to_skip  = offset % spc;
     3936    // takes the lock
     3937    _spin_lock_acquire( &_fat.fat_lock );
    16163938   
    1617     // get first cluster index
    1618     cluster = _fat.fd[fd_id].first_cluster;
     3939    // get inode
     3940    unsigned int code = _get_inode_from_path( pathname , &inode );
     3941
     3942    if ( code == 2 ) 
     3943    {
     3944        _spin_lock_release( &_fat.fat_lock );
     3945        _printf("\n[FAT ERROR] in _fat_mkdir() : path to parent not found"
     3946                " for directory <%s>\n", pathname );
     3947        return -2;
     3948    }
     3949    else if ( code == 3 ) 
     3950    {
     3951        _spin_lock_release( &_fat.fat_lock );
     3952        _printf("\n[FAT ERROR] in _fat_mkdir() : one name in path too long"
     3953                " for directory  <%s>\n", pathname );
     3954        return -3;
     3955    }
     3956    else if ( code == 0 )
     3957    {
     3958        _spin_lock_release( &_fat.fat_lock );
     3959        _printf("\n[FAT ERROR] in _fat_mkdir() : directory <%s> already exist\n",
     3960                pathname );
     3961        return -4;
     3962    }
     3963    else if ( code == 1 )   // directory not found => create
     3964    {
     3965        parent = inode;
    16193966
    16203967#if GIET_DEBUG_FAT
    16213968if ( _get_proctime() > GIET_DEBUG_FAT )
    1622 _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] get cluster %x\n",
    1623         x, y, p, cluster );
    1624 #endif
    1625 
    1626     // compute index of first cluster to be loaded
    1627     while ( clusters_to_skip )
    1628     {
    1629         cluster = _get_next_cluster( use_irq , cluster );
    1630         clusters_to_skip--;
    1631     }
    1632 
    1633     // variables used in the loop on clusters
    1634     int             todo_sectors;   // number of sectors still to be loaded
    1635     unsigned int    lba;            // first sector index on device
    1636     unsigned int    iter_sectors;   // number of sectors to load in iteration
    1637     unsigned int    src;            // pointer on target buffer
    1638 
    1639     // initialize these variables for the first iteration
    1640     todo_sectors  = count;
    1641     src           = (unsigned int)buffer;
    1642     lba           = cluster_to_lba(cluster) + sectors_to_skip;
    1643     if( count < (spc - sectors_to_skip) ) iter_sectors = count;
    1644     else                                  iter_sectors = spc - sectors_to_skip;
    1645 
    1646     // loop on the clusters
    1647     while ( todo_sectors > 0 )
    1648     {
     3969_printf("\n[DEBUG FAT] _fat_mkdir() : P[%d,%d,%d] create new directory <%s>\n",
     3970        x , y , p , pathname );
     3971#endif
     3972
     3973        // get directory name / error check already done by _get_inode_from_path()
     3974        char name[32];       
     3975        _get_last_name( pathname , name );
     3976
     3977        // allocate one cluster from FAT for the new directory
     3978        unsigned int cluster;
     3979        if ( _allocate_one_cluster( &cluster ) )
     3980        {
     3981            _spin_lock_release( &_fat.fat_lock );
     3982            _printf("\n[FAT ERROR] in _fat_mkdir() : no free cluster"
     3983                    " for directory <%s>\n" , pathname );
     3984            return -5;
     3985        }
     3986
     3987        // allocate a new inode and an empty Cache-File
     3988        child = _allocate_one_inode( name,
     3989                                     1,           // it's a directory
     3990                                     cluster, 
     3991                                     0,           // size not defined
     3992                                     0,           // count
     3993                                     0,           // dentry set by _add_dir_entry()
     3994                                     1 );         // cache_allocate
     3995
     3996        // introduce inode in Inode-Tree
     3997        _add_inode_in_tree( child , parent );
     3998 
     3999        // allocate and initialise one 4 Kbytes buffer and associated descriptor
     4000        _allocate_one_buffer( child,
     4001                              0,            // cluster_id,
     4002                              cluster );
     4003
     4004        _add_special_directories( child,
     4005                                  parent );
     4006
     4007        // add an entry in the parent directory Cache_file
     4008        if ( _add_dir_entry( child , parent ) )
     4009        {
     4010            _spin_lock_release( &_fat.fat_lock );
     4011            _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update parent directory"
     4012                    " for directory <%s>\n" , pathname );
     4013            return -6;
     4014        }
     4015
     4016        // update DATA region on block device for parent directory
     4017        if ( _update_device_from_cache( parent->levels,
     4018                                        parent->cache,
     4019                                        parent->name ) )
     4020        {
     4021            _spin_lock_release( &_fat.fat_lock );
     4022            _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update DATA region "
     4023                    " for parent of directory <%s>\n", pathname );
     4024            return -7;
     4025        }
     4026
     4027        // update FAT region on block device
     4028        if ( _update_device_from_cache( _fat.fat_cache_levels,
     4029                                        _fat.fat_cache_root,
     4030                                        "FAT" ) )
     4031        {
     4032            _spin_lock_release( &_fat.fat_lock );
     4033            _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update FAT region"
     4034                    " for directory <%s>\n", pathname );
     4035            return -8;
     4036        }
     4037
     4038        // update FS_INFO sector
     4039        if ( _update_fs_info() )
     4040        {
     4041            _spin_lock_release( &_fat.fat_lock );
     4042            _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update FS-INFO"
     4043                    " for directory <%s>\n", pathname );
     4044            return -9;
     4045        }
     4046
     4047        // update DATA region on block device for the new directory
     4048        if ( _update_device_from_cache( child->levels,   
     4049                                        child->cache,
     4050                                        child->name ) )
     4051        {
     4052            _spin_lock_release( &_fat.fat_lock );
     4053            _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update DATA region"
     4054                    " for directory <%s>\n", pathname );
     4055            return -10;
     4056        }
     4057    }  // end create directory
     4058
     4059    return 0;
     4060}  // end _fat_mkdir()
     4061
     4062
     4063
     4064
     4065
     4066/////////////////////////////////////////////////////////////////////////////////
     4067// The following function implements the giet_fat_list() system call.
     4068// It displays the content of a directory identified by the "pathname" argument.
     4069// It returns an error code if the pathname is not a directory.
     4070/////////////////////////////////////////////////////////////////////////////////
     4071// Returns 0 if success.
     4072// Returns a negative value if error:
     4073//   -1  : "FAT not initialised
     4074//   -2  : "Directory not found"
     4075//   -3  : "Name in path too long
     4076//   -4  : "Not a directory"
     4077//   -5  : "Cannot access directory"
     4078//   -6  : "Name too long truncated"
     4079/////////////////////////////////////////////////////////////////////////////////
     4080int _fat_list( char*  pathname )
     4081{
     4082    fat_inode_t*  inode;
     4083
     4084    // checking FAT initialised
     4085    if( _fat.initialised != FAT_INITIALISED )
     4086    {
     4087        _printf("\n[FAT ERROR] in _fat_list() : FAT not initialised\n");
     4088        return -1;
     4089    }
    16494090
    16504091#if GIET_DEBUG_FAT
    1651 if ( _get_proctime() > GIET_DEBUG_FAT )
    1652 _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] makes an IOC write"
    1653         "  cluster = %x / buffer = %x / lba = %x / sectors = %d\n",
    1654         x, y, p, cluster, src, lba, iter_sectors );
    1655 #endif
    1656 
    1657         if( _fat_ioc_access( use_irq,
    1658                              0,                 // write
     4092unsigned int procid  = _get_procid();
     4093unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
     4094unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
     4095unsigned int p       = procid & ((1<<P_WIDTH)-1);
     4096if ( _get_proctime() > GIET_DEBUG_FAT )
     4097_printf("\n[DEBUG FAT] _fat_list() : P[%d,%d,%d] enters for path <%s>\n",
     4098        x, y, p, pathname );
     4099#endif
     4100
     4101    // get inode
     4102    unsigned int code = _get_inode_from_path( pathname , &inode );
     4103
     4104    if ( (code == 1) || (code == 2) ) 
     4105    {
     4106        _printf("\n[FAT ERROR] in _fat_list() : directory <%s> not found\n", pathname );
     4107        return -2;
     4108    }
     4109    if ( code == 3 )
     4110    {
     4111        _printf("\n[FAT ERROR] in _fat_list() : name too long in path <%s>\n", pathname );
     4112        return -3;
     4113    }
     4114
     4115    // check found inode is a directory
     4116    if ( inode->is_dir == 0 )
     4117    {
     4118        _printf("\n[FAT ERROR] in _fat_list() : <%s> is not a directory\n", pathname );
     4119        return -4;
     4120    }
     4121
     4122#if GIET_DEBUG_FAT
     4123if ( _get_proctime() > GIET_DEBUG_FAT )
     4124_printf("\n[DEBUG FAT] _fat_list() : P[%d,%d,%d] found inode for path <%s>\n",
     4125        x, y, p, pathname );
     4126#endif
     4127
     4128    // scan directory up to end of directory / two embedded loops :
     4129    // - loop on the clusters allocated to the directory
     4130    // - loop on the directory entries in each 4 Kbytes buffer
     4131    unsigned char*     buffer; 
     4132    fat_cache_desc_t*  pdesc;
     4133    unsigned int       cluster_id = 0;     // cluster index in directory
     4134    unsigned int       offset     = 0;     // position in scanned buffer
     4135    unsigned int       lfn        = 0;     // number of lfn entries
     4136    unsigned int       nb_entries = 0;     // number of directory entries
     4137    unsigned int       done       = 0;     // end of directory found
     4138    unsigned int       attr;               // ATTR field value
     4139    unsigned int       ord;                // ORD field value
     4140    char               lfn1[16];           // temporary buffer for string in LFN1
     4141    char               lfn2[16];           // temporary buffer for string in LFN2
     4142    char               lfn3[16];           // temporary buffer for string in LFN3
     4143    char               name[36];           // directory entry full name
     4144    unsigned int       cluster;            // directory entry cluster index
     4145    unsigned int       size;               // directory entry size
     4146    unsigned int       is_dir;             // directory entry is a directory
     4147    unsigned int       is_vid;             // directory entry is volume_id
     4148
     4149    // TODO : define a method to transfer this information to user mode
     4150    _printf("\n<%s>   cluster = %x / lba = %x\n", pathname ,
     4151            inode->cluster , _cluster_to_lba( inode->cluster) );
     4152
     4153    while ( done == 0 )
     4154    {
     4155        // get one 4 Kytes buffer
     4156        if ( _get_buffer_from_cache( inode,
     4157                                     cluster_id,
     4158                                     &pdesc ) )
     4159        {
     4160            _printf("\n[FAT ERROR] in _fat_list() : cannot access <%s>\n", pathname );
     4161            return -5;
     4162        }
     4163        buffer = pdesc->buffer;
     4164
     4165        // scan this 4 Kbytes buffer
     4166        while ( (offset < 4096)  && (done == 0) )
     4167        {
     4168            attr = _read_entry( DIR_ATTR , buffer + offset , 0 );   
     4169            ord  = _read_entry( LDIR_ORD , buffer + offset , 0 );
     4170
     4171            if (ord == NO_MORE_ENTRY)                 // no more entry in directory => break
     4172            {
     4173                done = 1;
     4174            }
     4175            else if ( ord == FREE_ENTRY )             // free entry => skip
     4176            {
     4177                offset = offset + 32;
     4178            }
     4179            else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => get partial names
     4180            {
     4181                unsigned int seq = ord & 0x3;
     4182                lfn = (seq > lfn) ? seq : lfn;   
     4183                if      ( seq == 1 ) _get_name_from_long( buffer + offset, lfn1 );
     4184                else if ( seq == 2 ) _get_name_from_long( buffer + offset, lfn2 );
     4185                else if ( seq == 3 ) _get_name_from_long( buffer + offset, lfn3 );
     4186                offset = offset + 32;
     4187            }
     4188            else                                 // NORMAL entry
     4189            {
     4190                if      ( lfn == 0 )
     4191                {
     4192                    _get_name_from_short( buffer + offset , name );
     4193                }
     4194                else if ( lfn == 1 )
     4195                {
     4196                    _strcpy( name , lfn1 );
     4197                }   
     4198                else if ( lfn == 2 )
     4199                {
     4200                    _strcpy( name      , lfn1 );
     4201                    _strcpy( name + 13 , lfn2 );
     4202                }
     4203                else if ( lfn == 3 )
     4204                {
     4205                    _strcpy( name      , lfn1 );
     4206                    _strcpy( name + 13 , lfn2 );
     4207                    _strcpy( name + 26 , lfn3 );
     4208                }
     4209                   
     4210                is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     4211                is_vid  = ((attr & ATTR_VOLUME_ID) == ATTR_VOLUME_ID);
     4212                size    = (_read_entry( DIR_FILE_SIZE   , buffer + offset , 1 )      ) ;
     4213                cluster = (_read_entry( DIR_FST_CLUS_HI , buffer + offset , 1 ) << 16) |
     4214                          (_read_entry( DIR_FST_CLUS_LO , buffer + offset , 1 )      ) ;
     4215
     4216                if ( is_vid == 0 )
     4217                {
     4218                    // TODO : define a method to transfer this information to user mode
     4219                    if (is_dir) _printf("  DIR  | size = %X | cluster = %X | %s\n",
     4220                                        size , cluster, name );
     4221                    else        _printf("  FILE | size = %X | cluster = %X | %s\n",
     4222                                        size , cluster, name );
     4223                    nb_entries++;
     4224                }
     4225               
     4226                offset = offset + 32;
     4227                lfn    = 0;
     4228            }
     4229        }  // end loop on directory entries
     4230
     4231        if ( done == 0 )
     4232        {
     4233            cluster_id++;
     4234            offset = 0;
     4235        }
     4236    }  // end loop on buffers
     4237
     4238    // TODO : define a method to transfer this information to user mode
     4239    _printf("  total = %d entries\n", nb_entries );
     4240
     4241    return 0;
     4242} // end _fat_list()
     4243
     4244
     4245
     4246
     4247
     4248///////////////////////////////////////////////////////////////////////////////
     4249// This functiond load a file identified by the "pathname" argument into the
     4250// memory buffer defined by the "buffer_vbase" and "buffer_size" arguments.
     4251// It is intended to be called by the boot-loader, as it does not use the
     4252// dynamically allocated FAT structures (Inode-Tree, Fat_Cache or File-Cache,
     4253// File-Descriptor-Array).
     4254// It uses only the 512 bytes buffer defined in the FAT descriptor.
     4255///////////////////////////////////////////////////////////////////////////////
     4256// Returns  0 if success.
     4257// Returns negative value if error:
     4258//  -1  : "FAT not initialised"
     4259//  -2  : "File not found"
     4260//  -3  : "Buffer too small"
     4261//  -4  : "Cannot access block device"
     4262//  -5  : "Cannot access FAT on block device"
     4263///////////////////////////////////////////////////////////////////////////////
     4264int _fat_load_no_cache( char*        pathname,
     4265                        unsigned int buffer_vbase, 
     4266                        unsigned int buffer_size )
     4267{
     4268    // checking FAT initialised
     4269    if( _fat.initialised != FAT_INITIALISED )
     4270    {
     4271        _printf("\n[FAT ERROR] in _fat_load_no_cache() : FAT not initialised\n");
     4272        return -1;
     4273    }
     4274
     4275    unsigned int  file_size;
     4276    unsigned int  cluster;
     4277
     4278#if GIET_DEBUG_FAT
     4279unsigned int procid  = _get_procid();
     4280unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
     4281unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
     4282unsigned int p       = procid & ((1<<P_WIDTH)-1);
     4283if ( _get_proctime() > GIET_DEBUG_FAT )
     4284_printf("\n[DEBUG FAT] _fat_load_no_cache() : P[%d,%d,%d] enters for file <%s>\n",
     4285        x , y , p , pathname );
     4286#endif
     4287
     4288    // get file size, and cluster index in FAT
     4289    if ( _file_info_no_cache( pathname,
     4290                              &cluster,
     4291                              &file_size ) )
     4292    {
     4293        _printf("\n[FAT ERROR] in _fat_load_no_cache() : file <%s> not found\n",
     4294        pathname );
     4295        return -2;
     4296    }
     4297
     4298    // check buffer size
     4299    if ( file_size > buffer_size )
     4300    {
     4301        _printf("\n[FAT ERROR] in _fat_load_no_cache() : buffer too small : "
     4302                "file_size = %x / buffer_size = %x", file_size , buffer_size );
     4303        return -3;
     4304    }
     4305
     4306    // compute total number of clusters to read
     4307    unsigned int nb_clusters = file_size >> 12;
     4308    if ( file_size & 0xFFF ) nb_clusters++;
     4309
     4310    // initialise buffer address
     4311    unsigned int dst = buffer_vbase;
     4312
     4313    // loop on the clusters containing the file
     4314    while ( nb_clusters > 0 )
     4315    {
     4316        unsigned int lba = _cluster_to_lba( cluster );
     4317
     4318        if( _fat_ioc_access( 0,         // no descheduling
     4319                             1,         // read
    16594320                             lba,
    1660                              src,               // source buffer address
    1661                              iter_sectors ) )   // number of sectors
    1662         {
    1663             _printf("\n[FAT ERROR] in _fat_write() cannot write block %x\n", lba );
    1664             return -1;
     4321                             dst,
     4322                             8 ) )      // 8 blocks
     4323        {
     4324            _printf("\n[FAT ERROR] in _fat_no _cache_read() : cannot load lba %x", lba );
     4325            return -4;
    16654326        }
    16664327         
     4328
     4329        // compute next cluster index
     4330        unsigned int next;
     4331        if ( _next_cluster_no_cache( cluster , &next ) )
     4332        {
     4333            _printf("\n[FAT ERROR] in _fat_no _cache_read() : cannot get next cluster "
     4334                    " for cluster = %x\n", cluster );
     4335            return -5;
     4336        }
     4337       
    16674338        // update variables for next iteration
    1668         cluster      = _get_next_cluster( use_irq , cluster );
    1669         todo_sectors = todo_sectors - iter_sectors;
    1670         src          = src + (iter_sectors << 9);
    1671         lba          = cluster_to_lba(cluster);
    1672         if ( todo_sectors > spc ) iter_sectors = spc;
    1673         else                      iter_sectors = todo_sectors;
    1674     }
    1675 
    1676     // Update structure file descriptor, field file_size with
    1677     // the new file size if the file is bigger than the previous file
    1678     if ( ( offset + count ) > file_sectors )
    1679     {
    1680         _fat.fd[fd_id].file_size = (count + offset) << 9;
    1681     }
    1682 
    1683     // Update entry of directory with the new value
    1684     // of file size (Field : DIR_FILE_SIZE)
    1685     if ( _update_entry( use_irq, fd_id , DIR_FILE_SIZE , _fat.fd[fd_id].file_size ) )
    1686     {
    1687         _printf("\n[FAT ERROR] in _fat_write() update entry failed\n");
    1688         return -1;
     4339        nb_clusters = nb_clusters - 1;
     4340        dst         = dst + 4096;
     4341        cluster     = next;
    16894342    }
    16904343         
    1691     // returns number of sectors actually transfered
    1692     return count;
    1693 }  // end _fat_write()
    1694 
    1695 /////////////////////////////////////////////////////////////////////////////////
    1696 // Return stats of a file identified by "fd".
    1697 // (Only the file_size in sectors for this moment)
    1698 /////////////////////////////////////////////////////////////////////////////////
    1699 // Returns file size (on sectors) on success, -1 on failure.
    1700 /////////////////////////////////////////////////////////////////////////////////
    1701 int _fat_fstat( unsigned int fd_id )
    1702 {
    1703     unsigned int file_size    = 0;
    1704     unsigned int file_sectors = 0;
    1705 
    1706     if( (fd_id < GIET_OPEN_FILES_MAX) )
    1707     {
    1708         file_size = _fat.fd[fd_id].file_size;
    1709 
    1710         if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
    1711         else                     file_sectors = (file_size >> 9);
    1712 
    1713         return file_sectors;
    1714     }
    1715     else
    1716     {
    1717         _printf("\n[FAT ERROR] in _fat_fstat() : illegal file descriptor index\n");
    1718         return -1;
    1719     }
    1720 } // end _fat_fstat()
    1721 
    1722 /////////////////////////////////////////////////////////////////////////////////
    1723 // Close the file identified by the file_descriptor index.
    1724 /////////////////////////////////////////////////////////////////////////////////
    1725 // Returns 0 on success, -1 on failure.
    1726 /////////////////////////////////////////////////////////////////////////////////
    1727 int _fat_close( unsigned int fd_id )
    1728 {
    1729     if( (fd_id < GIET_OPEN_FILES_MAX) )
    1730     {
    1731         _fat.fd[fd_id].used = 0;
    1732         return 0;
    1733     }
    1734     else
    1735     {
    1736         _printf("\n[FAT ERROR] in _fat_close() : illegal file descriptor index\n");
    1737         return -1;
    1738     }
    1739 } // end fat_close()
    1740 
    1741 /////////////////////////////////////////////////////////////////////////////////
    1742 // The following function implement the user_level system call.
    1743 // The flags argument is not used, as file access modes are not implemented yet.
    1744 /////////////////////////////////////////////////////////////////////////////////
    1745 // Return the file descriptor index if success / return -1 if failure
    1746 /////////////////////////////////////////////////////////////////////////////////
    1747 int _fat_user_open( char*  pathname,         // absolute pathname from root
    1748                     unsigned int flags )     // unused: TODO
    1749 {
    1750     return _fat_open( 1,        // use descheduling mode if possible
    1751                       pathname,
    1752                       0 );      // no creation if not found
    1753 }
    1754 
    1755 /////////////////////////////////////////////////////////////////////////////////
    1756 // The following function implement the user_level system call.
    1757 // This function should be modified to respect the UNIX specification.
    1758 /////////////////////////////////////////////////////////////////////////////////
    1759 // Return number of sectors actually transfered if success / return -1 if failure
    1760 /////////////////////////////////////////////////////////////////////////////////
    1761 int _fat_user_read( unsigned int fd,        // file descriptor index
    1762                     void*        buffer,    // destination buffer
    1763                     unsigned int count,     // number of sectors to read
    1764                     unsigned int offset )   // number of sectors to skip
    1765 {
    1766     return _fat_read( 1,        // use descheduling mode if possible
    1767                       fd,
    1768                       buffer, 
    1769                       count, 
    1770                       offset );
    1771 }
    1772 
    1773 /////////////////////////////////////////////////////////////////////////////////
    1774 // The following function implement the user_level system call.
    1775 // This function should be modified to respect the UNIX specification.
    1776 /////////////////////////////////////////////////////////////////////////////////
    1777 // Return number of sectors actually transfered if success / return -1 if failure
    1778 /////////////////////////////////////////////////////////////////////////////////
    1779 int _fat_user_write( unsigned int fd,       // file descriptor
    1780                      void*        buffer,   // source buffer
    1781                      unsigned int count,    // number of sectors to write
    1782                      unsigned int offset )  // number of sectors to skip on file
    1783 {
    1784     return _fat_write( 1,       // use descheduling mode if possible
    1785                        fd,
    1786                        buffer, 
    1787                        count, 
    1788                        offset );
    1789 }
    1790 
    1791 /////////////////////////////////////////////////////////////////////////////////
    1792 int _fat_user_lseek( unsigned int fd_id,
    1793                      unsigned int offset,
    1794                      unsigned int whence )
    1795 {
    1796     _printf("\n[GIET ERROR] _fat_user_lseek() not implemented\n");
    1797     _exit();
     4344#if GIET_DEBUG_FAT
     4345if ( _get_proctime() > GIET_DEBUG_FAT )
     4346_printf("\n[DEBUG FAT] _fat_load_no_cache() : P[%d,%d,%d] loaded <%s> at vaddr = %x"
     4347        " / size = %x\n", x , y , p , pathname , buffer_vbase , file_size );
     4348#endif
     4349
    17984350    return 0;
    1799 }
     4351}  // end _fat_load_no_cache()
     4352
    18004353
    18014354
  • soft/giet_vm/giet_fat32/fat32.h

    r530 r587  
    22// File     : fat32.h
    33// Date     : 01/09/2013
    4 // Author   : Marco Jankovic / Alain Greiner
     4// Author   : Alain Greiner / Marco Jankovic
    55// Copyright (c) UPMC-LIP6
    66////////////////////////////////////////////////////////////////////////////////
     
    6868#define FS_SIGNATURE_POSITION_2           484 , 4
    6969#define FS_SIGNATURE_POSITION_3           508 , 4 
    70 #define FS_FREE_CLUSTER                   488 , 4
     70#define FS_FREE_CLUSTERS                  488 , 4
    7171#define FS_FREE_CLUSTER_HINT              492 , 4
    7272/*******************************************************************************/
     
    7474#define DIR_ENTRY_SIZE          32
    7575                   
     76#define NAME_MAX_SIZE           31
     77
    7678/******* Directory Entry Structure (32 bytes) **********************************/
    77 //                          offset | length
    78 #define DIR_NAME                 0 , 11   // dir_entry name
    79 #define DIR_ATTR                11 ,  1   // attributes
    80 #define DIR_NTRES               12 ,  1   // reserved for the OS       
    81 #define DIR_CRT_TIMES_TENTH     13 ,  1
    82 #define DIR_FST_CLUS_HI         20 ,  2   // cluster index 16 MSB bits
    83 #define DIR_WRT_TIME            22 ,  2   // time of last write
    84 #define DIR_WRT_DATE            24 ,  2   // date of last write
    85 #define DIR_FST_CLUS_LO         26 ,  2   // cluster index 16 LSB bit
    86 #define DIR_FILE_SIZE           28 ,  4   // file size (up to 4 giga bytes)
     79//                            offset | length
     80#define DIR_NAME                   0 , 11   // dir_entry name
     81#define DIR_ATTR                  11 ,  1   // attributes
     82#define DIR_NTRES                 12 ,  1   // reserved for the OS       
     83#define DIR_CRT_TIMES_TENTH       13 ,  1
     84#define DIR_FST_CLUS_HI           20 ,  2   // cluster index 16 MSB bits
     85#define DIR_WRT_TIME              22 ,  2   // time of last write
     86#define DIR_WRT_DATE              24 ,  2   // date of last write
     87#define DIR_FST_CLUS_LO           26 ,  2   // cluster index 16 LSB bit
     88#define DIR_FILE_SIZE             28 ,  4   // file size (up to 4 giga bytes)
    8789/*******************************************************************************/
    8890
    8991/******* LFN Directory Entry Structure  (32 bytes) *****************************/
    90 //                          offset | length
    91 #define LDIR_ORD                 0 ,  1   // Sequence number (from 0x01 to 0x0f)   
    92 #define LDIR_NAME_1              1 , 10   // name broken into 3 parts
    93 #define LDIR_ATTR               11 ,  1   // attributes (must be 0x0F)
    94 #define LDIR_TYPE               12 ,  1   // directory type (must be 0x00)
    95 #define LDIR_CHKSUM             13 ,  1   // checksum of name in short dir 
    96 #define LDIR_NAME_2             14 , 12
    97 #define LDIR_RSVD               26 ,  2   // artifact of previous fat (must be 0)
    98 #define LDIR_NAME_3             28 ,  4   
     92//                            offset | length
     93#define LDIR_ORD                   0 ,  1   // Sequence number (from 0x01 to 0x0f)   
     94#define LDIR_NAME_1                1 , 10   // name broken into 3 parts
     95#define LDIR_ATTR                 11 ,  1   // attributes (must be 0x0F)
     96#define LDIR_TYPE                 12 ,  1   // directory type (must be 0x00)
     97#define LDIR_CHKSUM               13 ,  1   // checksum of name in short dir 
     98#define LDIR_NAME_2               14 , 12
     99#define LDIR_RSVD                 26 ,  2   // artifact of previous fat (must be 0)
     100#define LDIR_NAME_3               28 ,  4   
    99101/*******************************************************************************/
    100102
    101103/***********************  DIR_ATTR values  (attributes) ************************/
    102 #define ATTR_READ_ONLY          0x01
    103 #define ATTR_HIDDEN             0x02
    104 #define ATTR_SYSTEM             0x04
    105 #define ATTR_VOLUME_ID          0x08
    106 #define ATTR_DIRECTORY          0x10
    107 #define ATTR_ARCHIVE            0x20
    108 #define ATTR_LONG_NAME_MASK     0x0f      // READ_ONLY|HIDDEN|SYSTEM|VOLUME_ID
     104#define ATTR_READ_ONLY            0x01
     105#define ATTR_HIDDEN               0x02
     106#define ATTR_SYSTEM               0x04
     107#define ATTR_VOLUME_ID            0x08
     108#define ATTR_DIRECTORY            0x10
     109#define ATTR_ARCHIVE              0x20
     110#define ATTR_LONG_NAME_MASK       0x0f      // READ_ONLY|HIDDEN|SYSTEM|VOLUME_ID
    109111/*******************************************************************************/
    110112
    111113/********************* DIR_ORD special values **********************************/
    112 #define FREE_ENTRY              0xE5     // this entry is free in the directory
    113 #define NO_MORE_ENTRY           0x00     // no more entry in the directory
     114#define FREE_ENTRY                0xE5     // this entry is free in the directory
     115#define NO_MORE_ENTRY             0x00     // no more entry in the directory
    114116/*******************************************************************************/
    115117
    116118/******************** CLuster Index Special Values *****************************/
    117 #define FREE_CLUSTER            0x00000000
    118 #define RESERVED_CLUSTER        0x00000001
    119 #define BAD_CLUSTER             0x0FFFFFF7
    120 #define END_OF_CHAIN_CLUSTER    0x0ffffff8
    121 /*******************************************************************************/
     119#define FREE_CLUSTER              0x00000000
     120#define RESERVED_CLUSTER          0x00000001
     121#define BAD_CLUSTER               0x0FFFFFF7
     122#define END_OF_CHAIN_CLUSTER_MIN  0x0ffffff8
     123#define END_OF_CHAIN_CLUSTER_MAX  0x0fffffff
     124/*******************************************************************************/
     125
     126
     127#define SEEK_SET                0
     128#define SEEK_CUR                1
    122129
    123130#define FAT_INITIALISED         0xBABEF00D
    124131
    125 /************ This struct defines a file descriptor ****************************/
    126 typedef struct file_descriptor_s
    127 {
    128    unsigned int  used;                      // descriptor contains an open file
    129    unsigned int  first_cluster;             // first cluster index on disk
    130    unsigned int  file_size;                 // number of bytes   
    131    unsigned int  lba_dir_entry;             // lba of dir_entry for an open file
    132    char          name[244];                 // pathname
    133 }  file_desc_t;
    134 /*******************************************************************************/
    135 
    136 /************ This struct describes a FAT32 disk *******************************/
    137 typedef struct fat32_fs_s
    138 {
    139     char            fat_cache[512];          // FAT cache: 1 sector 
    140     spin_lock_t     fat_lock;                // lock protecting exclusive access
    141     file_desc_t     fd[GIET_OPEN_FILES_MAX]; // file descriptors array
    142     unsigned int    initialised;             // 0xBABEF00D when FAT initialised
    143     unsigned int    sector_size;             // number of bytes (power of 2)
    144     unsigned int    sectors_per_cluster;     // power of 2 (must be greater than 4)
    145     unsigned int    cluster_size;            // sector_size * sector_per_cluster
    146     unsigned int    fat_sectors;             // number of sectors for 1 FAT copy
    147     unsigned int    fat_lba;                 // lba of first FAT sector
    148     unsigned int    data_lba;                // lba of first data sector 
    149     unsigned int    cache_lba;               // lba of sector loaded in fat_cache
    150     unsigned int    last_cluster_allocated;  // Last known cluster allocated
    151     unsigned int    number_free_cluster;     // number of free clusters
    152     unsigned int    fs_info_lba;             // lba of fs_info
    153 } fat32_fs_t;
    154 /*******************************************************************************/
     132#define O_RDONLY                0x01
     133#define O_CREATE                0x20
     134
     135/********************************************************************************
     136  This struct defines a non terminal node in a 64-tree implementing a File-Cache
     137  associated to an open file, or the Fat-Cache, associated to the FAT itself.
     138  Each node has 64 children, and we use the void* type, because the children
     139  can be non-terminal (fat_cache_node_t) or terminal (fat_cache_cluster_t).
     140********************************************************************************/
     141
     142typedef struct fat_cache_node_s
     143{
     144    void*              children[64];           // pointers on the 64 children
     145}   fat_cache_node_t;
     146
     147
     148/********************************************************************************
     149  This struct defines a cluster descriptor, that is a leaf cell in a 64-tree.
     150  Each cluster descriptor contains a pointer on a 4K bytes buffer, and the
     151  lba on block device.
     152********************************************************************************/
     153
     154typedef struct fat_cache_desc_s
     155{
     156    unsigned int       lba;                      // cluster lba on block device
     157    unsigned int       dirty;                    // modified if non zero
     158    unsigned char*     buffer;                   // pointer on the 4 Kbytes buffer
     159}   fat_cache_desc_t;
     160
     161
     162/********************************************************************************
     163  This struct defines a file/directory inode / size = 64 bytes
     164********************************************************************************/
     165
     166typedef struct fat_inode_s
     167{
     168    struct fat_inode_s*  parent;                 // parent directory inode
     169    struct fat_inode_s*  next;                   // next inode in same directory
     170    struct fat_inode_s*  child;                  // first children inode (dir only)
     171    fat_cache_node_t*    cache;                  // pointer on the file_cache root
     172    unsigned int         cluster;                // first cluster index in FAT
     173    unsigned int         size;                   // number of bytes (file only)
     174    unsigned int         count;                  // number open if file / 0 if dir
     175    unsigned short       dentry;                 // directory entry index in parent
     176    unsigned char        levels;                 // number of levels in file_cache
     177    unsigned char        is_dir;                 // directory if non zero
     178    char                 name[32];               // file  directory name
     179}   fat_inode_t;
     180
     181/********************************************************************************
     182  This struct defines a file descriptor (handler) / size = 16 bytes
     183********************************************************************************/
     184
     185typedef struct fat_file_desc_s
     186{
     187    unsigned int         seek;                   // current offset value (bytes)
     188    fat_inode_t*         inode;                  // pointer on inode
     189    char                 allocated;              // file descriptor allocated
     190    char                 read_only;              // write protected
     191    char                 reserved[6];            // reserved
     192}   fat_file_desc_t;
     193
     194/********************************************************************************
     195  This struct defines a FAT32 File system descriptor
     196 *******************************************************************************/
     197
     198typedef struct fat_desc_s
     199{
     200    unsigned char       block_buffer[512];       // one block buffer (for FS_INFO)
     201    fat_file_desc_t     fd[GIET_OPEN_FILES_MAX]; // file descriptors array
     202    spin_lock_t         fat_lock;                // global lock protecting FAT
     203    fat_inode_t*        inode_tree_root;         // Inode-Tree root pointer
     204    fat_cache_node_t*   fat_cache_root;          // Fat_Cache root pointer
     205    unsigned int        fat_cache_levels;        // number of levels in Fat-Cache
     206    unsigned int        block_buffer_lba;        // lba of block in block_buffer
     207    unsigned int        initialised;             // 0xBABEF00D when FAT initialised
     208    unsigned int        sector_size;             // must be 512
     209    unsigned int        cluster_size;            // must be 4096
     210    unsigned int        fat_lba;                 // lba of first FAT sector
     211    unsigned int        fat_sectors;             // number of sectors in FAT region
     212    unsigned int        data_lba;                // lba of first DATA sector 
     213    unsigned int        data_sectors;            // number of sectors inf DATA region
     214    unsigned int        fs_info_lba;             // lba of fs_info
     215    unsigned int        first_free_cluster;      // free cluster with smallest index
     216    unsigned int        free_clusters_number;    // total number of free clusters
     217}   fat_desc_t;
     218
    155219
    156220/*********************** Extern Functions  *************************************/
    157221
    158 extern int _fat_init( unsigned int use_irq );       // use IRQ if possible
    159 
    160 extern int _fat_open(  unsigned int use_irq,        // use IRQ if possible
    161                        char*  pathname,             // file pathname from root
    162                        unsigned int create );       // create new file if non zero
    163 
    164 extern int _fat_read(  unsigned int use_irq,        // use IRQ if possible
    165                        unsigned int fd_id,          // file descriptor index
    166                        void*        buffer,         // destination buffer
    167                        unsigned int count,          // number of sectors to read
    168                        unsigned int offset );       // offset sector in file
    169 
    170 extern int _fat_write( unsigned int use_irq,        // use IRQ if possible
    171                        unsigned int fd_id,          // file descriptor index
    172                        void*        buffer,                 // source buffer
    173                        unsigned int count,          // number of sectors to write
    174                        unsigned int offset );       // offset sector in file
    175 
    176 extern int _fat_fstat( unsigned int fd_id );        // file descriptor index
    177 
    178 extern int _fat_close( unsigned int fd_id );        // file descriptor index
    179 
    180 
    181 extern int _fat_user_open( char*        pathname,   // file pathname from root
    182                            unsigned int flags );    // unused
    183 
    184 extern int _fat_user_read(  unsigned int fd_id,     // file descriptor index
    185                             void*        buffer,    // destination buffer
    186                             unsigned int count,     // number of sectors to read
    187                             unsigned int offset );  // sectors to skip in file
    188 
    189 extern int _fat_user_write( unsigned int fd_id,     // file descriptor index
    190                             void*        buffer,    // source buffer
    191                             unsigned int count,     // number of sectors to write
    192                             unsigned int offset );  //  sectors to skip in file
    193 
    194 extern int _fat_user_lseek( unsigned int fd_id,
    195                             unsigned int offset,
    196                             unsigned int whence ); 
     222extern int _fat_init();         
     223
     224extern int _fat_open( char*        pathname,               // path from root
     225                      unsigned int flags );                // O_CREATE/O_RDONLY
     226
     227extern int _fat_close( unsigned int fd_id );               // file descriptor
     228
     229extern int _fat_file_info( unsigned int  fd_id,            // file descriptor
     230                           unsigned int* size,             // file size
     231                           unsigned int* offset );         // current offset
     232
     233extern int _fat_read( unsigned int fd_id,                  // file descriptor 
     234                      void*        buffer,                 // destination buffer
     235                      unsigned int count );                // number of bytes
     236
     237extern int _fat_write( unsigned int fd_id,                 // file descriptor
     238                       void*        buffer,                        // source buffer
     239                       unsigned int count );               // number of bytes
     240
     241extern int _fat_lseek( unsigned int fd_id,                 // file descriptor
     242                       unsigned int offset,                // new offset value
     243                       unsigned int whence );              // command type
     244
     245extern int _fat_remove( char*        pathname,             // path from root
     246                        unsigned int should_be_dir );      // for checking
     247
     248extern int _fat_rename( char*  old_path,                   // path from root
     249                        char*  new_path );                 // path from root
     250
     251extern int _fat_mkdir( char* pathname );                   // path from root
     252
     253extern int _fat_list( char* pathname );                    // path from root
     254
     255extern int _fat_load_no_cache( char*        pathname,      // path from root
     256                               unsigned int buffer_vbase,  // buffer base
     257                               unsigned int buffer_size ); // buffer size
    197258
    198259/*******************************************************************************/
Note: See TracChangeset for help on using the changeset viewer.