Index: trunk/kernel/vfs/fatfs.c
===================================================================
--- trunk/kernel/vfs/fatfs.c	(revision 246)
+++ trunk/kernel/vfs/fatfs.c	(revision 265)
@@ -46,5 +46,5 @@
  
 //////////////////////////////////////////////////////////////////////////////////////////
-//              FATFS private and static functions 
+//              FATFS specific and static functions 
 //////////////////////////////////////////////////////////////////////////////////////////
 
@@ -74,9 +74,215 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This function display the content of the FATFS context.
+// This function return an integer record value (one, two, or four bytes) 
+// from a memory buffer, taking into account endianness.
+//////////////////////////////////////////////////////////////////////////////////////////
+// @ offset        : first byte of record in buffer.
+// @ size          : record length in bytes (1/2/4).
+// @ buffer        : pointer on buffer base.
+// @ little endian : the most significant byte has the highest address when true.
+// @ return the integer value in a 32 bits word.
+//////////////////////////////////////////////////////////////////////////////////////////
+static uint32_t fatfs_get_record( uint32_t    offset,
+                                  uint32_t    size,
+                                  uint8_t   * buffer,
+                                  uint32_t    little_endian )
+{
+    uint32_t n;
+    uint32_t res  = 0;
+
+    if ( little_endian)
+    {
+        for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
+    }
+    else
+    {
+        for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
+    }
+    return res;
+
+}  // end fatfs_get_record()
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// This static function retun in the <name> buffer a short name stored in
+// a SFN FATFS directory entry.
+/////////////////////////i////////////////////////////////////////////////////////////////
+// @ buffer   : pointer on buffer containing the directory entry.
+// @ name     : [out] buffer allocated by the caller.
+//////////////////////////////////////////////////////////////////////////////////////////
+static void fatfs_get_name_from_short( uint8_t * buffer,
+                                       char    * name )
+{
+    uint32_t i;
+    uint32_t j = 0;
+
+    // get name
+    for ( i = 0; i < 8 && buffer[i] != ' '; i++ )
+    {
+        name[j] = to_lower( buffer[i] );
+        j++;
+    }
+
+    // get extension
+    for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ )
+    {
+        // we entered the loop so there is an extension. add the dot
+        if ( i == 8 )
+        {
+            name[j] = '.';
+            j++;
+        }
+
+        name[j] = to_lower( buffer[i] );
+        j++;
+    }
+
+    name[j] = '\0';
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// This static function retun in the <name> buffer a partial name stored in
+// a LFN FATFS directory entry.
+/////////////////////////i////////////////////////////////////////////////////////////////
+// @ buffer   : pointer on buffer containing the directory entry.
+// @ name     : [out] buffer allocated by the caller.
+//////////////////////////////////////////////////////////////////////////////////////////
+static void fatfs_get_name_from_long( uint8_t * buffer,
+                                      char    * name )
+{
+    uint32_t   name_offset   = 0;
+    uint32_t   buffer_offset = get_length(LDIR_ORD);
+    uint32_t   l_name_1      = get_length(LDIR_NAME_1);
+    uint32_t   l_name_2      = get_length(LDIR_NAME_2);
+    uint32_t   l_name_3      = get_length(LDIR_NAME_3);
+    uint32_t   l_attr        = get_length(LDIR_ATTR);
+    uint32_t   l_type        = get_length(LDIR_TYPE);
+    uint32_t   l_chksum      = get_length(LDIR_CHKSUM);
+    uint32_t   l_rsvd        = get_length(LDIR_RSVD);
+
+    uint32_t   j             = 0;
+    uint32_t   eof           = 0;
+
+    while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) )
+    {
+        while (j != l_name_1 && !eof )
+        {
+            if ( (buffer[buffer_offset] == 0x00) || 
+                 (buffer[buffer_offset] == 0xFF) )
+            {
+                eof = 1;
+                continue;
+            }
+            name[name_offset] = buffer[buffer_offset];
+            buffer_offset += 2;
+            j += 2;
+            name_offset++;
+        }
+
+        buffer_offset += (l_attr + l_type + l_chksum);
+        j = 0;
+
+        while (j != l_name_2 && !eof )
+        {
+            if ( (buffer[buffer_offset] == 0x00) || 
+                 (buffer[buffer_offset] == 0xFF) )
+            {
+                eof = 1;
+                continue;
+            }
+            name[name_offset] = buffer[buffer_offset];
+            buffer_offset += 2;
+            j += 2;
+            name_offset++;
+        }
+
+        buffer_offset += l_rsvd;
+        j = 0;
+
+        while (j != l_name_3 && !eof )
+        {
+            if ( (buffer[buffer_offset] == 0x00) || 
+                 (buffer[buffer_offset] == 0xFF) )
+            {
+                eof = 1;
+                continue;
+            }
+            name[name_offset] = buffer[buffer_offset];
+            buffer_offset += 2;
+            j += 2;
+            name_offset++;
+        }
+    }
+    name[name_offset] = 0;
+
+} // end get_name_from_long()
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// This function returns the FATFS cluster index of a page identified by its page
+// index in the file, using the FAT mapper. It scans the FAT mapper, starting from the
+// FATFS cluster index allocated to the first page of the file, until it reaches the 
+// searched page. The FAT mapper is automatically updated in case of miss. 
+// This function can be called by any thread running in any cluster, as it uses the
+// RPC_FATFS_GET_CLUSTER to access the remote FAT mapper if required.
+// We use a RPC to scan the FAT because the RPC_FIFO will avoid contention
+// in the cluster containing the FAT mapper, and the RPC latency is not critical
+// compared to the device access latency.
+//////////////////////////////////////////////////////////////////////////////////////////
+// @ ctx	       : pointer on local FATFS context.
+// @ first_cluster : first cluster allocated to a file in FATFS.
+// @ page_index    : index of searched page in file (one page occupies one cluster).
+// @ cluster_index : [out] pointer on buffer for FATFS cluster index.
+// @ return 0 if success / return EIO if a FAT cluster miss cannot be solved.
+//////////////////////////////////////////////////////////////////////////////////////////
+static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx,
+                                         uint32_t      first_cluster,
+                                         uint32_t      page_index,
+                                         uint32_t    * cluster_index )
+{
+    uint32_t searched_cluster;   // searched FATFS cluster index
+    error_t  error;
+
+    // get extended pointer on FAT mapper
+    xptr_t fat_mapper_xp = ctx->fat_mapper_xp;
+
+    // get cluster cxy and local pointer on FAT mapper
+    cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
+    mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
+
+    if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
+    {
+        error = fatfs_get_cluster( fat_mapper_ptr,
+                                   first_cluster,
+                                   page_index,
+                                   &searched_cluster );
+    }
+    else                                 // FAT mapper is remote
+    {
+        rpc_fatfs_get_cluster_client( fat_mapper_cxy,
+                                      fat_mapper_ptr,
+                                      first_cluster,
+                                      page_index,
+                                      &searched_cluster,
+                                      &error );
+    }
+    
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot access FAT\n", __FUNCTION__ );
+        return error;
+    }
+
+    // return success
+    *cluster_index = searched_cluster;
+    return 0;
+
+}  // end fatfs_cluster_from_index()
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//              FATFS specific but extern functions 
+//////////////////////////////////////////////////////////////////////////////////////////
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void fatfs_ctx_display()
 {
-    uint32_t      type      = FS_TYPE_FATFS;
     vfs_ctx_t   * vfs_ctx   = &fs_context[FS_TYPE_FATFS];
     fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
@@ -99,218 +305,9 @@
 }
 
-//////////////////////////////////////////////////////////////////////////////////////////
-// This function return an integer record value (one, two, or four bytes) 
-// from a memory buffer, taking into account endianness.
-//////////////////////////////////////////////////////////////////////////////////////////
-// @ offset        : first byte of record in buffer.
-// @ size          : record length in bytes (1/2/4).
-// @ buffer        : pointer on buffer base.
-// @ little endian : the most significant byte has the highest address when true.
-// @ return the integer value in a 32 bits word.
-//////////////////////////////////////////////////////////////////////////////////////////
-static uint32_t fatfs_get_record( uint32_t    offset,
-                                  uint32_t    size,
-                                  uint8_t   * buffer,
-                                  uint32_t    little_endian )
-{
-    uint32_t n;
-    uint32_t res  = 0;
-
-    if ( little_endian)
-    {
-        for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
-    }
-    else
-    {
-        for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
-    }
-    return res;
-
-}  // end fatfs_get_record()
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// This static function retun in the <name> buffer a short name stored in
-// a SFN FATFS directory entry.
-/////////////////////////i////////////////////////////////////////////////////////////////
-// @ buffer   : pointer on buffer containing the directory entry.
-// @ name     : [out] buffer allocated by the caller.
-//////////////////////////////////////////////////////////////////////////////////////////
-static void fatfs_get_name_from_short( uint8_t * buffer,
-                                       char    * name )
-{
-    uint32_t i;
-    uint32_t j = 0;
-
-    // get name
-    for ( i = 0; i < 8 && buffer[i] != ' '; i++ )
-    {
-        name[j] = to_lower( buffer[i] );
-        j++;
-    }
-
-    // get extension
-    for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ )
-    {
-        // we entered the loop so there is an extension. add the dot
-        if ( i == 8 )
-        {
-            name[j] = '.';
-            j++;
-        }
-
-        name[j] = to_lower( buffer[i] );
-        j++;
-    }
-
-    name[j] = '\0';
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// This static function retun in the <name> buffer a partial name stored in
-// a LFN FATFS directory entry.
-/////////////////////////i////////////////////////////////////////////////////////////////
-// @ buffer   : pointer on buffer containing the directory entry.
-// @ name     : [out] buffer allocated by the caller.
-//////////////////////////////////////////////////////////////////////////////////////////
-static void fatfs_get_name_from_long( uint8_t * buffer,
-                                      char    * name )
-{
-    uint32_t   name_offset   = 0;
-    uint32_t   buffer_offset = get_length(LDIR_ORD);
-    uint32_t   l_name_1      = get_length(LDIR_NAME_1);
-    uint32_t   l_name_2      = get_length(LDIR_NAME_2);
-    uint32_t   l_name_3      = get_length(LDIR_NAME_3);
-    uint32_t   l_attr        = get_length(LDIR_ATTR);
-    uint32_t   l_type        = get_length(LDIR_TYPE);
-    uint32_t   l_chksum      = get_length(LDIR_CHKSUM);
-    uint32_t   l_rsvd        = get_length(LDIR_RSVD);
-
-    uint32_t   j             = 0;
-    uint32_t   eof           = 0;
-
-    while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) )
-    {
-        while (j != l_name_1 && !eof )
-        {
-            if ( (buffer[buffer_offset] == 0x00) || 
-                 (buffer[buffer_offset] == 0xFF) )
-            {
-                eof = 1;
-                continue;
-            }
-            name[name_offset] = buffer[buffer_offset];
-            buffer_offset += 2;
-            j += 2;
-            name_offset++;
-        }
-
-        buffer_offset += (l_attr + l_type + l_chksum);
-        j = 0;
-
-        while (j != l_name_2 && !eof )
-        {
-            if ( (buffer[buffer_offset] == 0x00) || 
-                 (buffer[buffer_offset] == 0xFF) )
-            {
-                eof = 1;
-                continue;
-            }
-            name[name_offset] = buffer[buffer_offset];
-            buffer_offset += 2;
-            j += 2;
-            name_offset++;
-        }
-
-        buffer_offset += l_rsvd;
-        j = 0;
-
-        while (j != l_name_3 && !eof )
-        {
-            if ( (buffer[buffer_offset] == 0x00) || 
-                 (buffer[buffer_offset] == 0xFF) )
-            {
-                eof = 1;
-                continue;
-            }
-            name[name_offset] = buffer[buffer_offset];
-            buffer_offset += 2;
-            j += 2;
-            name_offset++;
-        }
-    }
-    name[name_offset] = 0;
-
-} // end get_name_from_long()
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// This function returns the FATFS cluster index of a page identified by its page
-// index in the file, using the FAT mapper. It scans the FAT mapper, starting from the
-// FATFS cluster index allocated to the first page of the file, until it reaches the 
-// searched page. The FAT mapper is automatically updated in case of miss. 
-// This function can be called by any thread running in any cluster, as it uses the
-// RPC_FATFS_GET_CLUSTER to access the remote FAT mapper if required.
-// We use a RPC to scan the FAT because the RPC_FIFO will avoid contention
-// in the cluster containing the FAT mapper, and the RPC latency is not critical
-// compared to the device access latency.
-//////////////////////////////////////////////////////////////////////////////////////////
-// @ ctx	       : pointer on local FATFS context.
-// @ first_cluster : first cluster allocated to a file in FATFS.
-// @ page_index    : index of searched page in file (one page occupies one cluster).
-// @ cluster_index : [out] pointer on buffer for FATFS cluster index.
-// @ return 0 if success / return EIO if a FAT cluster miss cannot be solved.
-//////////////////////////////////////////////////////////////////////////////////////////
-static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx,
-                                         uint32_t      first_cluster,
-                                         uint32_t      page_index,
-                                         uint32_t    * cluster_index )
-{
-    uint32_t searched_cluster;   // searched FATFS cluster index
-    error_t  error;
-
-    // get extended pointer on FAT mapper
-    xptr_t fat_mapper_xp = ctx->fat_mapper_xp;
-
-    // get cluster cxy and local pointer on FAT mapper
-    cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
-    mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
-
-    if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
-    {
-        error = fatfs_get_cluster( fat_mapper_ptr,
-                                   first_cluster,
-                                   page_index,
-                                   &searched_cluster );
-    }
-    else                                 // FAT mapper is remote
-    {
-        rpc_fatfs_get_cluster_client( fat_mapper_cxy,
-                                      fat_mapper_ptr,
-                                      first_cluster,
-                                      page_index,
-                                      &searched_cluster,
-                                      &error );
-    }
-    
-    if( error )
-    {
-        printk("\n[ERROR] in %s : cannot access FAT\n", __FUNCTION__ );
-        return error;
-    }
-
-    // return success
-    *cluster_index = searched_cluster;
-    return 0;
-
-}  // end fatfs_cluster_from_index()
-
-//////////////////////////////////////////////////////////////////////////////////////////
-//              FATFS specific but extern function (used by RPC_FATFS_GET_CLUSTER) 
-//////////////////////////////////////////////////////////////////////////////////////////
-
 /////////////////////////////////////////////
 error_t fatfs_get_cluster( mapper_t * mapper,
-                           uint32_t   first_cluster,
-                           uint32_t   searched_page,
-                           uint32_t * cluster )
+                           uint32_t   first_cluster_id,
+                           uint32_t   page_index,
+                           uint32_t * searched_cluster_id )
 {
     page_t   * current_page_desc;      // pointer on current page descriptor
@@ -319,16 +316,18 @@
     uint32_t   current_page_offset;    // offset of slot in current page
     uint32_t   page_count_in_file;     // index of page in file (index in linked list)
-    uint32_t   current_cluster;        // content of current FAT slot
-
-    fatfs_dmsg("\n[INFO] %s : enters / first_cluster_id = %d / searched_page = %d\n",
-               __FUNCTION__ , first_cluster , searched_page );
-
-#if CONFIG_FATFS_DEBUG
+    uint32_t   current_cluster_id;     // content of current FAT slot
+
+    assert( (page_index > 0) , __FUNCTION__ , "no FAT access required for first page\n");
+
+    fatfs_dmsg("\n[INFO] %s : enters / mapper = %x / first_cluster_id = %d / page_index = %d\n",
+               __FUNCTION__ , first_cluster_id , page_index );
+
+#if (CONFIG_FATFS_DEBUG > 1)
     uint32_t * buf = (uint32_t *)ppm_page2vaddr( mapper_get_page ( mapper , 0 ) );
     uint32_t line , word;
-    printk("\n***  FAT content for first 128 entries ***\n");
-    for( line = 0 ; line < 8 ; line++ )
-    {
-        printk("%d : ");
+    printk("\n***  FAT mapper content for first 256 entries ***\n");
+    for( line = 0 ; line < 16 ; line++ )
+    {
+        printk("%X : ", line );
         for( word = 0 ; word < 16 ; word++ ) printk("%X ", buf[(line<<4) + word] );
         printk("\n");
@@ -340,10 +339,10 @@
 
     // initialize loop variable
-    current_page_index  = first_cluster / slots_per_page;
-    current_page_offset = first_cluster % slots_per_page;
+    current_page_index  = first_cluster_id / slots_per_page;
+    current_page_offset = first_cluster_id % slots_per_page;
     page_count_in_file  = 0;
 
     // scan FAT (i.e. traverse FAT linked list)
-    while( page_count_in_file <= searched_page )
+    while( page_count_in_file <= page_index )
     {
 
@@ -360,16 +359,16 @@
 
         // get FAT slot content 
-        current_cluster = current_page_buffer[current_page_offset];
+        current_cluster_id = current_page_buffer[current_page_offset];
 
         // update loop variables
-        current_page_index  = current_cluster / slots_per_page;
-        current_page_offset = current_cluster % slots_per_page;
+        current_page_index  = current_cluster_id / slots_per_page;
+        current_page_offset = current_cluster_id % slots_per_page;
         page_count_in_file++;
     }
     
     fatfs_dmsg("\n[INFO] %s : exit / cluster_id = %d\n",
-               __FUNCTION__ , current_cluster );
-
-    *cluster = current_cluster;
+               __FUNCTION__ , current_cluster_id );
+
+    *searched_cluster_id = current_cluster_id;
     return 0;
 
@@ -550,23 +549,50 @@
     else                 // it is a normal inode mapper
     {
-        // get first cluster index from inode extension
-        uint32_t  first_cluster = (uint32_t)(intptr_t)inode->extend;
-
-        fatfs_dmsg("\n[INFO] %s : for inode %x / first cluster_id = %d\n",
-                   __FUNCTION__ , inode , first_cluster );
-    
-        // compute FATFS_cluster index for the accessed page
-        uint32_t cluster = 0;
-        error_t  error = fatfs_cluster_from_index( fatfs_ctx,
-                                                   first_cluster,
-                                                   index,
-                                                   &cluster );
-        if( error ) return EIO;
-
-        // get lba from cluster
-        uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , cluster );
+        uint32_t  searched_cluster_id;
+
+        // get first_cluster_id from inode extension
+        uint32_t  first_cluster_id = (uint32_t)(intptr_t)inode->extend;
+
+        fatfs_dmsg("\n[INFO] %s : for inode %x / first_cluster_id = %d\n",
+                   __FUNCTION__ , inode , first_cluster_id );
+
+        // compute cluster_id
+        if( index == 0 )            // no need to access FAT mapper
+        {
+            searched_cluster_id = first_cluster_id;
+        }
+        else                        // FAT mapper access required
+        {
+            // get cluster and local pointer on FAT mapper
+            xptr_t     fat_mapper_xp  = fatfs_ctx->fat_mapper_xp;
+            cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
+            mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
+
+            // access FAT mapper
+            if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
+            {
+                error = fatfs_get_cluster( fat_mapper_ptr,
+                                           first_cluster_id,
+                                           index,
+                                           &searched_cluster_id );
+            }
+            else                                 // FAT mapper is remote
+            {
+                rpc_fatfs_get_cluster_client( fat_mapper_cxy,
+                                              fat_mapper_ptr,
+                                              first_cluster_id,
+                                              index,
+                                              &searched_cluster_id,
+                                              &error );
+            }
+
+            if( error )  return EIO;
+        }
+
+        // get lba from cluster_id
+        uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id );
 
         fatfs_dmsg("\n[INFO] %s : for inode %x / page = %d / cluster_id = %d / lba = %x\n",
-                   __FUNCTION__ , inode , index , cluster , lba );
+                   __FUNCTION__ , inode , index , searched_cluster_id , lba );
 
         // access device
@@ -584,5 +610,5 @@
 }  // end fatfs_mapper_move_page()
 
-/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
 error_t fatfs_inode_load( vfs_inode_t * parent_inode,
                           char        * name,
@@ -629,4 +655,17 @@
         // get page base
         base = ppm_page2vaddr( page );
+
+#if (CONFIG_FATFS_DEBUG > 1)
+    uint32_t * buf = (uint32_t *)base;
+    uint32_t line , word;
+    printk("\n*** DIRECTORY content for first 16 entries ***\n");
+    for( line = 0 ; line < 16 ; line++ )
+    {
+        printk("%X : ", line );
+        for( word = 0 ; word < 8 ; word++ ) printk("%X ", buf[(line<<4) + word] );
+        printk("\n");
+    }
+#endif
+
 
         // scan this page until end of directory, end of page, or name found
