Index: trunk/kernel/vfs/fatfs.c
===================================================================
--- trunk/kernel/vfs/fatfs.c	(revision 10)
+++ trunk/kernel/vfs/fatfs.c	(revision 23)
@@ -2,6 +2,6 @@
  * fatfs.c - FATFS file system API implementation.
  *
- * Author    Mohamed Lamine Karaoui (2015)
- *           Alain Greiner (2016)
+ * Author    Mohamed Lamine Karaoui (2014,2015)
+ *           Alain Greiner (2016,2017)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -32,13 +32,19 @@
 #include <rpc.h>
 #include <mapper.h>
+#include <cluster.h>
 #include <dev_ioc.h>
 #include <fatfs.h>
 
-
 //////////////////////////////////////////////////////////////////////////////////////////
+//          Extern  variables         
+//////////////////////////////////////////////////////////////////////////////////////////
+
+extern vfs_ctx_t        fs_context[FS_TYPES_NR];   // allocated in vfs.c file
+
+extern remote_barrier_t global_barrier;            // allocated dans kernel_init.c
+ 
 //////////////////////////////////////////////////////////////////////////////////////////
 // FATFS specific functions : these functions cannot be called by the VFS 
 //////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////
 
 //////////////////////////////////////////////////////////
@@ -46,5 +52,5 @@
                                         uint32_t      cluster )
 {
-    return (ctx->cluster_begin_lba + ((cluster - 2) * ctx->sectors_per_cluster));
+    return (ctx->cluster_begin_lba + ((cluster - 2) << 3));
 }
 
@@ -95,4 +101,35 @@
 
 }  // end fatfs_get_cluster()
+
+///////////////////////////////////////////////////////////////////////////////////////
+// This static 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 get_record_from_buffer( 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 get_record_from_buffer()
+
 
 
@@ -162,20 +199,188 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////
+//          The following functions are called by the VFS.
 ///////////////////////////////////////////////////////////////////////////////////////
-// Generic API : the following functions are called by the VFS, 
-//               and must be defined by all isupported file systems.
-///////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////
-error_t fatfs_inode_create( struct vfs_inode_s * vfs_inode )
-{
-    printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ );
-    hal_core_sleep();
-
+
+
+///////////////////
+xptr_t fatfs_init()
+{
+    kmem_req_t    req;
+    fatfs_ctx_t * fatfs_ctx;       // local pointer on FATFS context 
+    vfs_ctx_t   * vfs_ctx;         // local pointer on VFS context 
+    xptr_t        root_inode_xp;   // extended pointer on root inode
+    error_t       error;
+
+    // get local pointer on VFS context for FATFS
+    vfs_ctx = &fs_context[FS_TYPE_FATFS];
+
+    // get number of kernel instances and extended pointer on global barrier 
+    cluster_t * cluster     = LOCAL_CLUSTER;
+    uint32_t    nb_clusters = cluster->x_size * cluster->y_size;
+    xptr_t      barrier_xp  = XPTR( cluster->io_cxy , &global_barrier );
+
+    ///// step 1 : all clusters allocate memory for FATFS context 
+
+    // allocate memory for FATFS context extension
+	req.type    = KMEM_FATFS_CTX;
+	req.size    = sizeof(fatfs_ctx_t);
+    req.flags   = AF_KERNEL | AF_ZERO;
+	fatfs_ctx   = (fatfs_ctx_t *)kmem_alloc( &req );
+
+    if( fatfs_ctx == NULL ) 
+    {
+        printk("\n[PANIC] in %s : no memory for FATFS context\n", __FUNCTION__ );
+        hal_core_sleep();
+    }
+    
+    ///// step 2 : only cluster_0 access device and creates root inode
+
+    if( local_cxy == 0 )
+    {
+        // create VFS root inode
+        error = vfs_inode_create( XPTR_NULL,        // no parent dentry
+                                  FS_TYPE_FATFS,
+                                  INODE_TYPE_DIR,
+                                  0,                // attr
+                                  0,                // rights
+                                  0,                // uid
+                                  0,                // gid
+                                  &root_inode_xp );
+
+        assert( (error == 0 ) , __FUNCTION__ , "cannot create VFS root inode" );
+
+        // initialize VFS context / access device to initialize FATFS context
+        error = fatfs_ctx_init( vfs_ctx,
+                                fatfs_ctx,
+                                root_inode_xp );
+
+        // create FATFS root inode
+        error = fatfs_inode_create( GET_PTR( root_inode_xp ) , 
+                                    fatfs_ctx->root_dir_cluster );
+
+        if( error )
+        {
+            printk("\n[PANIC] in %s : cannot create FATFS root inode\n", __FUNCTION__ );
+            hal_core_sleep();
+        }
+
+    }
+
+    //////////////// synchronize all clusters
+    remote_barrier( barrier_xp , nb_clusters );
+
+    ///// step 3 : all others clusters initialize both context and extension
+
+    if( local_cxy != 0 )
+    {
+        // copy VFS context from remote cluster_0 to local cluster
+        hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ), 
+                           XPTR( 0 , vfs_ctx ),
+                           sizeof(vfs_ctx_t) );
+
+        // copy FATFS context from remote cluster_0 to local cluster
+        hal_remote_memcpy( XPTR( local_cxy , fatfs_ctx ), 
+                           XPTR( 0 , vfs_ctx->extend ) ,
+                           sizeof(fatfs_ctx_t) );
+
+        // update extend field in local copy of VFS context
+        vfs_ctx->extend = fatfs_ctx;
+    }
+
+    return root_inode_xp;
+
+}  // end fatfs_init()
+
+//////////////////////////////////////////////
+error_t fatfs_ctx_init( vfs_ctx_t   * vfs_ctx,
+                        fatfs_ctx_t * fatfs_ctx,
+                        xptr_t        root_inode_xp )
+{
+    error_t  error;
+    uint8_t  buffer[512];    // buffer for boot record
+
+    // make a synchronous access to IOC device to read the boot record from device
+    error = dev_ioc_sync_read( buffer , 0 , 1 );
+    assert( (error == 0) , __FUNCTION__ , "cannot access FAT boot record" );
+
+    // check sector size from boot record
+    uint32_t sector_size = get_record_from_buffer( BPB_BYTSPERSEC , buffer , 1 );
+    assert( (sector_size == 512) , __FUNCTION__ , "sector size must be 512 bytes" );
+
+    // check cluster size from boot record
+    uint32_t nb_sectors = get_record_from_buffer( BPB_SECPERCLUS , buffer , 1 );
+    assert( (nb_sectors == 8) , __FUNCTION__ , "cluster size must be 8 sectors" );
+
+    // check number of FAT copies from boot record
+    uint32_t nb_fats = get_record_from_buffer( BPB_NUMFATS , buffer , 1 );
+    assert( (nb_fats == 1) , __FUNCTION__ , "number of FAT copies must be 1" );
+
+    // get & check number of sectors in FAT from boot record
+    uint32_t fat_sectors = get_record_from_buffer( BPB_FAT32_FATSZ32 , buffer , 1 );
+    assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ , "FAT not multiple of 16 sectors");
+
+    // get and check root cluster from boot record
+    uint32_t root_cluster = get_record_from_buffer( BPB_FAT32_ROOTCLUS , buffer , 1 );
+    assert( (root_cluster == 2) , __FUNCTION__ , "Root cluster index must be  2");
+
+    // get FAT lba from boot record
+    uint32_t fat_lba = get_record_from_buffer( BPB_RSVDSECCNT , buffer , 1 );
+    
+    // allocate a mapper for the FAT itself
+    mapper_t * fat_mapper = mapper_create();
+    assert( (fat_mapper != NULL) , __FUNCTION__ , "no memory for FAT mapper" );
+
+    // initialize the FATFS context
+    fatfs_ctx->fat_begin_lba         = fat_lba;
+    fatfs_ctx->fat_sectors_count     = fat_sectors; 
+    fatfs_ctx->bytes_per_sector      = sector_size;
+    fatfs_ctx->bytes_per_cluster     = sector_size * nb_sectors;
+    fatfs_ctx->cluster_begin_lba     = fat_lba + fat_sectors;
+    fatfs_ctx->root_dir_cluster      = 2;
+    fatfs_ctx->last_allocated_sector = 0;    // TODO ???
+    fatfs_ctx->last_allocated_index  = 0;    // TODO ???
+    fatfs_ctx->fat_mapper_xp         = XPTR( local_cxy , fat_mapper );
+
+    // initialize the VFS context
+    vfs_ctx->type    = FS_TYPE_FATFS;
+    vfs_ctx->attr    = 0;                    // not READ_ONLY / not SYNC
+    vfs_ctx->count   = fat_sectors << 10;    // total number of sectors in data region
+    vfs_ctx->blksize = 512;                  // number of bytes per sector
+    vfs_ctx->root_xp = root_inode_xp;
+    vfs_ctx->extend  = fatfs_ctx;
+
+    spinlock_init( &vfs_ctx->lock );
+
+    bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES );
+
+    return 0;
+
+}  // end fatfs_ctx_init()
+ 
+
+
+////////////////////////////////////////////////////
+void fatfs_ctx_destroy( struct vfs_ctx_s * vfs_ctx )
+{
+    kmem_req_t    req;
+    fatfs_ctx_t * fatfs_ctx;
+
+    // get pointer on FATFS context extension
+    fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
+
+    req.type = KMEM_FATFS_INODE;
+    req.ptr  = fatfs_ctx;
+    kmem_free( &req );
+}
+
+
+////////////////////////////////////////////////////
+error_t fatfs_inode_create( vfs_inode_t * vfs_inode,
+                            uint32_t      first_cluster )
+{
     kmem_req_t      req;
     fatfs_inode_t * fatfs_inode;
 
-    // allocate memory for fatfs inode
+    // allocate memory for FATFS inode extension
 	req.type    = KMEM_FATFS_INODE;
 	req.size    = sizeof(fatfs_inode_t);
@@ -185,37 +390,29 @@
     if( fatfs_inode == NULL ) return ENOMEM;
 
-    // initialise ramfs_inode 
-    fatfs_inode->first_cluster = 0;   // TODO ???
-    fatfs_inode->ctx           = (fatfs_ctx_t *)vfs_inode->ctx->extend;
+    // link FATFS inode to VFS inode
+    vfs_inode->extend = fatfs_inode;
+
+    // initialise FATFS inode 
+    fatfs_inode->first_cluster = first_cluster;
  
-    // link fatfs_inode to vfs_inode
-    vfs_inode->extend = fatfs_inode;
-
     return 0;
-
-}
-
-//////////////////////////////////////////////////////
-void fatfs_inode_destroy( struct vfs_inode_s * inode )
-{
-    printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ );
-    hal_core_sleep();
-}
-
-//////////////////////////////////////////////////
-error_t fatfs_ctx_create( struct vfs_ctx_s * ctx )
-{
-    printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ );
-    hal_core_sleep();
-
-    return 0;
-}
-
-////////////////////////////////////////////////
-void fatfs_ctx_destroy( struct vfs_ctx_s * ctx )
-{
-    printk("\n[PANIC] %s not fully implemented yet\n", __FUNCTION__ );
-    hal_core_sleep();
-}
+}
+
+///////////////////////////////////////////////////
+void fatfs_inode_destroy( vfs_inode_t * vfs_inode )
+{
+    kmem_req_t      req;
+    fatfs_inode_t * fatfs_inode;
+
+    // get pointer on FATFS inode 
+    fatfs_inode = (fatfs_inode_t *)vfs_inode->extend;
+
+    req.type = KMEM_FATFS_INODE;
+    req.ptr  = fatfs_inode;
+    kmem_free( &req );
+
+	vfs_inode->extend = NULL;
+}
+
 
 ////////////////////////////////////////////////
@@ -223,19 +420,13 @@
                                   bool_t   is_read )
 {
-    // get source buffer base address
-    char * buffer = (char *)ppm_page2base( page );
+    // get memory buffer base address
+    uint8_t * buffer = (uint8_t *)ppm_page2base( page );
  
     // get pointer on source mapper and page index from page descriptor
-    mapper_t * src_mapper  = page->mapper;
+    mapper_t * mapper      = page->mapper;
     uint32_t   page_index  = page->index;
 
-    if( src_mapper == NULL)
-    {
-        printk("\n[PANIC] in %s : no mapper for this page\n", __FUNCTION__ );
-        hal_core_sleep();
-    }
-
     // get VFS inode pointer from mapper
-    vfs_inode_t * vfs_inode = src_mapper->inode;
+    vfs_inode_t * vfs_inode = mapper->inode;
 
     // get FATFS inode pointer for VFS inode
@@ -246,5 +437,5 @@
 
     // get FATFS context pointer from FATFS inode
-    fatfs_ctx_t * fatfs_ctx = fatfs_inode->ctx;
+    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_inode->ctx->extend;
 
     // get number of sectors 
