Index: soft/giet_vm/giet_fat32/fat32.c
===================================================================
--- soft/giet_vm/giet_fat32/fat32.c	(revision 746)
+++ soft/giet_vm/giet_fat32/fat32.c	(revision 750)
@@ -45,4 +45,5 @@
 #include <mmc_driver.h>
 #include <tty0.h>
+#include <stdio.h>
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -112,22 +113,4 @@
                             unsigned int buf_vaddr,
                             unsigned int count );
-
-//////////////////////////////////////////////////////////////////////////////////
-// The following function returns in the "desc" argument a pointer on a buffer 
-// descriptor contained in a File_Cache, or in the Fat_Cache. 
-// The searched buffer is idenfified by the "inode" and "cluster_id" arguments.
-// If the "inode" pointer is not NULL, the searched cache is a File-Cache.
-// If the "inode" pointer is NULL, the searched cache is the Fat-Cache, 
-// The "cluster_id" argument is the buffer index in the file (or in the FAT). 
-// In case of miss, it allocate a 4 Kbytes buffer and a cluster descriptor 
-// from the local kernel heap, and calls the _fat_ioc_access() function to load 
-// the missing cluster from the block device.
-// It returns 0 on success.
-// It returns 1 on error.
-//////////////////////////////////////////////////////////////////////////////////
-
-static unsigned int _get_buffer_from_cache( fat_inode_t*        inode,
-                                            unsigned int        cluster_id,
-                                            fat_cache_desc_t**  desc );
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -963,148 +946,4 @@
 
 
-//////////////////////////////////////////////////////////////////////
-static unsigned int _get_buffer_from_cache( fat_inode_t*        inode,
-                                            unsigned int        cluster_id,
-                                            fat_cache_desc_t**  desc )
-{
-    // get cache pointer and levels
-    fat_cache_node_t*   node;         // pointer on a 64-tree node
-    unsigned int        level;        // cache level
-
-    if ( inode == NULL )   // searched cache is the Fat-Cache
-    {
-        node   = _fat.fat_cache_root;
-        level  = _fat.fat_cache_levels;
-
-#if (GIET_DEBUG_FAT & 1)
-if ( _get_proctime() > GIET_DEBUG_FAT )
-_printf("\n[DEBUG FAT] _get_buffer_from_cache(): enters in FAT-Cache"
-        " for cluster_id = %d\n", cluster_id );
-#endif
-    }
-    else                   // searched cache is a File-Cache
-    {
-        // add cache levels if needed
-        while ( _get_levels_from_size( (cluster_id + 1) * 4096 ) > inode->levels )
-        {
-#if (GIET_DEBUG_FAT & 1)
-if ( _get_proctime() > GIET_DEBUG_FAT )
-_printf("\n[DEBUG FAT] _get_buffer_from_cache(): adding a File-Cache level\n" );
-#endif
-
-            inode->cache = _allocate_one_cache_node( inode->cache );
-            inode->levels++;
-        }
-
-        node   = inode->cache;
-        level  = inode->levels;
-
-#if (GIET_DEBUG_FAT & 1)
-if ( _get_proctime() > GIET_DEBUG_FAT )
-_printf("\n[DEBUG FAT] _get_buffer_from_cache(): enters in File-Cache <%s>"
-        " for cluster_id = %d\n", inode->name , cluster_id );
-#endif
-    }
-
-    // search the 64-tree cache from top to bottom 
-    while ( level )
-    {
-        // compute child index at each level
-        unsigned int index = (cluster_id >> (6*(level-1))) & 0x3F;
-
-        if ( level == 1 )        // last level => children are cluster descriptors
-        {
-            fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index];
-
-            if ( pdesc == NULL )      // miss 
-            {
-                // get missing cluster index lba
-                unsigned int lba;
-                unsigned int next;
-                unsigned int current = inode->cluster;
-                unsigned int count   = cluster_id;
-
-                if ( inode == NULL )      // searched cache is the Fat-Cache
-                {
-
-#if (GIET_DEBUG_FAT & 1)
-if ( _get_proctime() > GIET_DEBUG_FAT )
-_printf("\n[DEBUG FAT] _get_buffer_from_cache(): miss in FAT-Cache for cluster_id %d\n",
-        cluster_id );
-#endif
-                    lba = _fat.fat_lba + (cluster_id << 3);
-                }
-                else                      // searched cache is a File-Cache
-                {
-
-#if (GIET_DEBUG_FAT & 1)
-if ( _get_proctime() > GIET_DEBUG_FAT )
-_printf("\n[DEBUG FAT] _get_buffer_from_cache(): miss in File-Cache <%s> "
-        "for cluster_id %d\n", inode->name, cluster_id );
-#endif
-                    while ( count )
-                    { 
-                        if ( _get_fat_entry( current , &next ) ) return 1;
-                        current = next;
-                        count--;
-                    }
-                    lba = _cluster_to_lba( current );
-                }
-
-                // allocate 4K buffer
-                void* buf = _malloc( 4096 );
-
-                // load one cluster (8 blocks) from block device
-                if ( _fat_ioc_access( 1,         // descheduling
-                                      1,         // to memory
-                                      lba,
-                                      (unsigned int)buf,
-                                      8 ) )
-                {
-                    _free( buf );
-                    _printf("\n[FAT ERROR] _get_buffer_from_cache()"
-                            ": cannot access block device for lba = %x\n", lba );
-                    return 1;
-                }
-
-                // allocate buffer descriptor
-                pdesc          = _malloc( sizeof(fat_cache_desc_t) );
-                pdesc->lba     = lba;
-                pdesc->buffer  = buf;
-                pdesc->dirty   = 0;
-                node->children[index] = pdesc;
-
-#if (GIET_DEBUG_FAT & 1)
-if ( _get_proctime() > GIET_DEBUG_FAT )
-_printf("\n[DEBUG FAT] _get_buffer_from_cache(): buffer loaded from device"
-        " at vaddr = %x\n", (unsigned int)buf );
-#endif
-            }
-
-            // return pdesc pointer
-            *desc = pdesc;
-
-            // prepare next iteration
-            level--;
-        }
-        else                      // not last level => children are 64-tree nodes
-        {
-            fat_cache_node_t* child = (fat_cache_node_t*)node->children[index];
-            if ( child == NULL )  // miss 
-            {
-                // allocate a cache node if miss
-                child = _allocate_one_cache_node( NULL );
-                node->children[index] = child;    
-            }
-
-            // prepare next iteration
-            node = child;
-            level--;
-        }
-    } // end while
-
-    return 0;
-}  // end _get_buffer_from_cache()
-
 
 
@@ -1170,5 +1009,5 @@
     fat_cache_desc_t*  pdesc;
     unsigned int*      buffer;
-    if ( _get_buffer_from_cache( NULL,               // Fat-Cache
+    if ( _fat_buffer_from_cache( NULL,               // Fat-Cache
                                  cluster_id,
                                  &pdesc ) ) return 1;
@@ -1195,5 +1034,5 @@
     fat_cache_desc_t*  pdesc;
     unsigned int*      buffer; 
-    if ( _get_buffer_from_cache( NULL,               // Fat-Cache
+    if ( _fat_buffer_from_cache( NULL,               // Fat-Cache
                                  cluster_id,
                                  &pdesc ) )  return 1;           
@@ -1679,5 +1518,5 @@
     {
         // get one 4 Kytes buffer from File_Cache  
-        if ( _get_buffer_from_cache( inode,
+        if ( _fat_buffer_from_cache( inode,
                                      cluster_id,
                                      &pdesc ) )   return 1;
@@ -1761,5 +1600,5 @@
     {
         // get one 4 Kytes buffer from File_Cache  
-        if ( _get_buffer_from_cache( parent,
+        if ( _fat_buffer_from_cache( parent,
                                      cluster_id,
                                      &pdesc ) )   return 1;
@@ -1819,5 +1658,5 @@
         if ( offset >= 4096 )  // new buffer required
         {
-            if ( _get_buffer_from_cache( parent,
+            if ( _fat_buffer_from_cache( parent,
                                          cluster_id + 1,
                                          &pdesc ) )      return 1;
@@ -1993,5 +1832,5 @@
     fat_cache_desc_t*  pdesc;
 
-    if ( _get_buffer_from_cache( inode->parent,
+    if ( _fat_buffer_from_cache( inode->parent,
                                  cluster_id,
                                  &pdesc ) ) return 1;
@@ -2010,5 +1849,5 @@
                 break;
 
-            if ( _get_buffer_from_cache( inode->parent,
+            if ( _fat_buffer_from_cache( inode->parent,
                                          cluster_id - 1,
                                          &pdesc ) )   return 1;
@@ -2046,5 +1885,5 @@
     unsigned int       offset     = (inode->dentry & 0x7F)<<5;
 
-    if ( _get_buffer_from_cache( inode->parent,
+    if ( _fat_buffer_from_cache( inode->parent,
                                  cluster_id,
                                  &pdesc ) )    return 1;
@@ -2131,5 +1970,5 @@
         // get one 4 Kytes buffer from parent File_Cache  
         fat_cache_desc_t*  pdesc;
-        if ( _get_buffer_from_cache( parent,
+        if ( _fat_buffer_from_cache( parent,
                                      cluster_id,
                                      &pdesc ) )    return 2;
@@ -2148,5 +1987,5 @@
             ord  = _read_entry( LDIR_ORD , buffer + offset , 0 );
 
-            if (ord == NO_MORE_ENTRY)                 // no more entry in directory => break
+            if (ord == NO_MORE_ENTRY)                 // no more entry => break
             {
                 found = -1;
@@ -3187,7 +3026,7 @@
 
 
-/////////////////////////////////////////////////////////////////////////////////
-// The following function implements the "giet_fat_read()" system call,
-// but can also be used by the kernel in physical addressing mode.
+///////////////////////////////////////////////////////////////////////////////////
+// The following function implements the "giet_fat_read()" and "giet_fat_pread')"
+// system calls, but can also be used by the kernel in physical addressing mode.
 // It transfers <count> bytes from the File_Cache associated to the file
 // identified by <fd_id>, to the destination buffer defined by <vaddr>.
@@ -3196,5 +3035,5 @@
 // the physical  address is computed as extend[15:0] | vaddr[31:0]
 // In case of miss in the File_Cache, it loads all involved clusters into cache.
-/////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
 // Returns the number of bytes actually transfered on success.
 // Returns a negative value on error:
@@ -3207,5 +3046,7 @@
                unsigned int vaddr,          // destination buffer vaddr
                unsigned int count,          // number of bytes to read
-               unsigned int extend )        // physical address extension
+               unsigned int extend,         // physical address extension
+               unsigned int offset,         // forced file offset
+               unsigned int modes )         // special modes
 {
 
@@ -3217,7 +3058,7 @@
 if ( _get_proctime() > GIET_DEBUG_FAT )
 _printf("\n[DEBUG FAT] _fat_read(): P[%d,%d,%d] enters at cycle %d\n"
-        "  fd = %d / vaddr = %x / bytes = %x / extend = %x\n",
+        "  fd = %d / vaddr = %x / bytes = %x / extend = %x / forced_offset = %x\n",
         x , y , p , _get_proctime(),
-        fd_id , vaddr , count , extend );
+        fd_id , vaddr , count , extend , offset );
 #endif
 
@@ -3225,5 +3066,5 @@
     if( _fat.initialized != FAT_INITIALIZED )
     {
-        _printf("\n[FAT ERROR] _fat_read(): FAT not initialized\n");
+        _printf("\n[FAT ERROR] in _fat_read(): FAT not initialized\n");
         return GIET_FAT32_NOT_INITIALIZED;
     }
@@ -3232,12 +3073,12 @@
     if ( fd_id >= GIET_OPEN_FILES_MAX )
     {
-        _printf("\n[FAT ERROR] _fat_read(): illegal file descriptor\n");
+        _printf("\n[FAT ERROR] in _fat_read(): illegal file descriptor\n");
         return GIET_FAT32_INVALID_FD;
     }
 
-    // check file is open
+    // check file open
     if ( _fat.fd[fd_id].allocated == 0 )
     {
-        _printf("\n[FAT ERROR] _fat_read(): file not open\n");
+        _printf("\n[FAT ERROR] in _fat_read(): file not open\n");
         return GIET_FAT32_NOT_OPEN;
     }
@@ -3249,7 +3090,11 @@
     _atomic_or( &psched->context[ltid].slot[CTX_LOCKS_ID] , LOCKS_MASK_FAT ); 
            
+    // get special modes
+    unsigned int physical_addressing = modes & FAT_PADDR_MODE;
+    unsigned int forced_offset       = modes & FAT_FORCED_OFFSET;
+
     // get file inode pointer and offset
     fat_inode_t* inode  = _fat.fd[fd_id].inode;
-    unsigned int seek   = _fat.fd[fd_id].seek;
+    unsigned int seek   = forced_offset ? offset : _fat.fd[fd_id].seek;
 
     // check seek versus file size
@@ -3259,5 +3104,5 @@
         _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
 
-        _printf("\n[FAT ERROR] _fat_read(): seek larger than file size"
+        _printf("\n[FAT ERROR] in _fat_read(): offset larger than file size"
                 " / seek = %x / file_size = %x\n",
                 seek , inode->size );
@@ -3293,5 +3138,5 @@
         unsigned char*     cbuf;
         fat_cache_desc_t*  pdesc;
-        if ( _get_buffer_from_cache( inode, 
+        if ( _fat_buffer_from_cache( inode, 
                                      cluster_id,
                                      &pdesc ) )
@@ -3300,5 +3145,5 @@
             _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
 
-            _printf("\n[FAT ERROR] _fat_read(): cannot load file <%s>\n",
+            _printf("\n[FAT ERROR] in _fat_read(): cannot load file <%s>\n",
                     inode->name );
             return GIET_FAT32_IO_ERROR;
@@ -3338,5 +3183,5 @@
 
         // move data 
-        if ( (extend & 0xFFFF0000) == 0 )         // no physical addressing
+        if ( physical_addressing == 0 )           // no physical addressing
         {
             char* dest = (char*)(vaddr + done);
@@ -3346,5 +3191,5 @@
         {
             unsigned int flags;
-            paddr_t pdest    = (((paddr_t)(extend & 0x0000FFFF))<<32) + vaddr + done;
+            paddr_t pdest    = (((paddr_t)extend)<<32) + vaddr + done;
             paddr_t psource  = _v2p_translate( (unsigned int)source, &flags );
             _physical_memcpy( pdest , psource , nbytes );
@@ -3360,6 +3205,6 @@
 #endif
 
-    // update seek
-    _fat.fd[fd_id].seek += done;
+    // update seek if required
+    if ( forced_offset == 0 ) _fat.fd[fd_id].seek += done;
 
     // release lock
@@ -3379,6 +3224,6 @@
 // identified by <fd_id>, from the source buffer defined by <vaddr>.
 // It uses the current file offset defined in the file descriptor.
-// If the <extend> 16 MSB bits are non zero, it uses physical addressing:
-// the physical  address is computed as extend[15:0] | vaddr[31:0]
+// If required by the <modes> argument, the physical  address is computed
+// as extend[15:0] | vaddr[31:0]
 // It increases the file size and allocate new clusters if (count + offset) 
 // is larger than the current file size. Then it loads and updates all 
@@ -3397,5 +3242,6 @@
                 unsigned int vaddr,    // source buffer vaddr
                 unsigned int count,    // number of bytes to write
-                unsigned int extend )  // physical address extension
+                unsigned int extend,   // physical address extension
+                unsigned int modes )   // special modes
 {
     // checking FAT initialized
@@ -3443,4 +3289,7 @@
         return GIET_FAT32_READ_ONLY;
     }
+
+    // get special modes
+    unsigned int physical_addressing = modes & FAT_PADDR_MODE;
 
     // get file inode pointer and seek 
@@ -3544,5 +3393,5 @@
         unsigned char*     cbuf;
         fat_cache_desc_t*  pdesc;
-        if ( _get_buffer_from_cache( inode,   
+        if ( _fat_buffer_from_cache( inode,   
                                      cluster_id,  
                                      &pdesc ) )   
@@ -3590,5 +3439,5 @@
 
         // move data
-        if ( (extend & 0xFFFF0000) == 0 )     // no physical addressing
+        if ( physical_addressing == 0 )     // no physical addressing
         {
             char* source = (char*)(vaddr + done);
@@ -3598,5 +3447,5 @@
         {
             unsigned int flags;
-            paddr_t      psource = (((paddr_t)(extend & 0x0000FFFF))<<32) + vaddr + done;
+            paddr_t      psource = (((paddr_t)extend)<<32) + vaddr + done;
             paddr_t      pdest   = _v2p_translate( (unsigned int)dest , &flags );
             _physical_memcpy( pdest , psource , nbytes );
@@ -4437,5 +4286,5 @@
     else if ( !info.is_dir )
     {
-        _printf("\n[FAT ERROR] _fat_readdir(): not a directory\n" );
+        _printf("\n[FAT ERROR] in _fat_readdir(): not a directory\n" );
         return GIET_FAT32_NOT_A_DIRECTORY;
     }
@@ -4454,7 +4303,10 @@
     while ( 1 )
     {
-        if ( _fat_read( fd_id, (unsigned int)&buf, sizeof(buf), 0 ) != sizeof(buf) )
-        {
-            _printf("\n[FAT ERROR] _fat_readdir(): can't read entry\n" );
+        if ( _fat_read( fd_id, 
+                        (unsigned int)&buf, 
+                        DIR_ENTRY_SIZE,
+                        0, 0, 0 )  != sizeof(buf) )
+        {
+            _printf("\n[FAT ERROR] in _fat_readdir(): can't read entry\n" );
             return GIET_FAT32_IO_ERROR;
         }
@@ -4516,5 +4368,5 @@
 
     return GIET_FAT32_OK;
-}
+}  // end _fat_readdir()
 
 
@@ -4627,4 +4479,164 @@
 
 
+//////////////////////////////////////////////////////////////////////////////////
+// The following function returns in the "desc" argument a pointer on a buffer 
+// descriptor contained in a File_Cache, or in the Fat_Cache. 
+// The searched buffer is idenfified by the "inode" and "cluster_id" arguments.
+// If the "inode" pointer is not NULL, the searched cache is a File-Cache.
+// If the "inode" pointer is NULL, the searched cache is the Fat-Cache, 
+// The "cluster_id" argument is the buffer index in the file (or in the FAT). 
+// In case of miss, it allocate a 4 Kbytes buffer and a cluster descriptor 
+// from the local kernel heap, and calls the _fat_ioc_access() function to load 
+// the missing cluster from the block device.
+//////////////////////////////////////////////////////////////////////////////////
+// It returns 0 on success.
+// It returns 1 on error.
+//////////////////////////////////////////////////////////////////////////////////
+int _fat_buffer_from_cache( fat_inode_t*        inode,
+                            unsigned int        cluster,
+                            fat_cache_desc_t**  desc )
+{
+    // get cache pointer and levels
+    fat_cache_node_t*   node;         // pointer on a 64-tree node
+    unsigned int        level;        // cache level
+
+    if ( inode == NULL )   // searched cache is the Fat-Cache
+    {
+        node   = _fat.fat_cache_root;
+        level  = _fat.fat_cache_levels;
+
+#if (GIET_DEBUG_FAT & 1)
+if ( _get_proctime() > GIET_DEBUG_FAT )
+_printf("\n[DEBUG FAT] _fat_buffer_from_cache(): enters in FAT-Cache"
+        " for cluster = %d\n", cluster );
+#endif
+    }
+    else                   // searched cache is a File-Cache
+    {
+        // add cache levels if needed
+        while ( _get_levels_from_size( (cluster + 1) * 4096 ) > inode->levels )
+        {
+#if (GIET_DEBUG_FAT & 1)
+if ( _get_proctime() > GIET_DEBUG_FAT )
+_printf("\n[DEBUG FAT] _fat_buffer_from_cache(): adding a File-Cache level\n" );
+#endif
+
+            inode->cache = _allocate_one_cache_node( inode->cache );
+            inode->levels++;
+        }
+
+        node   = inode->cache;
+        level  = inode->levels;
+
+#if (GIET_DEBUG_FAT & 1)
+if ( _get_proctime() > GIET_DEBUG_FAT )
+_printf("\n[DEBUG FAT] _fat_buffer_from_cache(): enters in File-Cache <%s>"
+        " for cluster = %d\n", inode->name , cluster );
+#endif
+    }
+
+    // search the 64-tree cache from top to bottom 
+    while ( level )
+    {
+        // compute child index at each level
+        unsigned int index = (cluster >> (6*(level-1))) & 0x3F;
+
+        if ( level == 1 )        // last level => children are cluster descriptors
+        {
+            fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index];
+
+            if ( pdesc == NULL )      // miss 
+            {
+                // get missing cluster index lba
+                unsigned int lba;
+                unsigned int next;
+                unsigned int current = inode->cluster;
+                unsigned int count   = cluster;
+
+                if ( inode == NULL )      // searched cache is the Fat-Cache
+                {
+
+#if (GIET_DEBUG_FAT & 1)
+if ( _get_proctime() > GIET_DEBUG_FAT )
+_printf("\n[DEBUG FAT] _fat_buffer_from_cache(): miss in FAT-Cache for cluster %d\n",
+        cluster );
+#endif
+                    lba = _fat.fat_lba + (cluster << 3);
+                }
+                else                      // searched cache is a File-Cache
+                {
+
+#if (GIET_DEBUG_FAT & 1)
+if ( _get_proctime() > GIET_DEBUG_FAT )
+_printf("\n[DEBUG FAT] _fat_buffer_from_cache(): miss in File-Cache <%s> "
+        "for cluster %d\n", inode->name, cluster );
+#endif
+                    while ( count )
+                    { 
+                        if ( _get_fat_entry( current , &next ) ) return 1;
+                        current = next;
+                        count--;
+                    }
+                    lba = _cluster_to_lba( current );
+                }
+
+                // allocate a 4 Kbytes buffer in cluster running the calling thread
+                void* buf = _malloc( 4096 );
+
+                // load one cluster (8 blocks) from block device
+                if ( _fat_ioc_access( 1,         // descheduling
+                                      1,         // to memory
+                                      lba,
+                                      (unsigned int)buf,
+                                      8 ) )
+                {
+                    _free( buf );
+                    _printf("\n[FAT ERROR] _fat_buffer_from_cache()"
+                            ": cannot access block device for lba = %x\n", lba );
+                    return 1;
+                }
+
+                // allocate buffer descriptor
+                pdesc          = _malloc( sizeof(fat_cache_desc_t) );
+                pdesc->lba     = lba;
+                pdesc->buffer  = buf;
+                pdesc->dirty   = 0;
+                node->children[index] = pdesc;
+
+#if (GIET_DEBUG_FAT & 1)
+if ( _get_proctime() > GIET_DEBUG_FAT )
+_printf("\n[DEBUG FAT] _fat_buffer_from_cache(): buffer loaded from device"
+        " at vaddr = %x\n", (unsigned int)buf );
+#endif
+            }
+
+            // return pdesc pointer
+            *desc = pdesc;
+
+            // prepare next iteration
+            level--;
+        }
+        else                      // not last level => children are 64-tree nodes
+        {
+            fat_cache_node_t* child = (fat_cache_node_t*)node->children[index];
+            if ( child == NULL )  // miss 
+            {
+                // allocate a cache node if miss
+                child = _allocate_one_cache_node( NULL );
+                node->children[index] = child;    
+            }
+
+            // prepare next iteration
+            node = child;
+            level--;
+        }
+    } // end while
+
+    return 0;
+}  // end _fat_buffer_from_cache()
+
+
+
+
 // Local Variables:
 // tab-width: 4
