/*
 * fatfs.h - FATFS file system API definition.
 *
 * Author    Mohamed Lamine Karaoui (2015)
 *           Alain Greiner (2016)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _FATFS_H_
#define _FATFS_H_

#include <hal_types.h>
#include <rwlock.h>

/****  Forward declarations  ****/

struct mapper_s;
struct device_s;
struct vfs_inode_s;
struct vfs_ctx_s;
struct page_s;

/*****************************************************************************************
 * This structure defines a FATFS specific context extension. 
 ****************************************************************************************/

typedef struct fatfs_ctx_s
{
    rwlock_t          lock;                  /*! TODO protect what ???                  */
    uint32_t          fat_begin_lba;         /*! first lba of FAT region                */
    uint32_t          fat_sectors_count;     /*! number of sectors in FAT region        */
    uint32_t          bytes_per_sector;      /*!                                        */
    uint32_t          bytes_per_cluster;     /*!                                        */
    uint32_t          cluster_begin_lba;     /*! first lba of data region on device     */
    uint32_t          sectors_per_cluster;   /*!                                        */
    uint32_t          rootdir_first_cluster; /*                                         */
    uint32_t          last_allocated_sector; /*!                                        */
    uint32_t          last_allocated_index;  /*! TODO last allocated cluster ???        */
    xptr_t            fat_mapper_xp;         /*! FAT mapper (in IO cluster)             */ 
}
fatfs_ctx_t;

/*****************************************************************************************
 * This structure defines the FAT specific inode extension (versus the VFS inode).
 ****************************************************************************************/

typedef struct fatfs_inode_s
{
    struct fatfs_ctx_s * ctx;                /*! local pointer on the FATFS context     */ 
	uint32_t             first_cluster;      /*! first cluster for this file/dir        */ 
}
fatfs_inode_t;



/*****************************************************************************************
 * This function returns the LBA of the first sector of a FAT cluster.
 * This function can be called by any thread running in any cluster.
 *****************************************************************************************
 * @ ctx	  :	pointer on FATFS context.
 * @ cluster  :	cluster index in FATFS.
 * # return the lba value.
 ****************************************************************************************/
inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx,
                                        uint32_t      cluster );

/*****************************************************************************************
 * This function scan the FAT (File Allocation Table), stored in the FAT mapper,
 * and return the FATFS cluster index for a given page of a given file.
 * It must be called by a thread running in the cluster containing the FAT mapper
 * (can be a local thread or a RPC thread).
 * The FAT is actually an array of uint32_t slots. Each slot in this array contains the 
 * index of another slot in this array, to form one linked list for each file stored on
 * device in the RAMFS file system. This index in the FAT array is also the index of the
 * FATFS cluster on the device. One FATFS cluster is supposed to contain one PPM page. 
 * For a given file, the entry point in the FAT is simply the index of the FATFS cluster 
 * containing the first page of the file. The mapper being a cache, this function 
 * automatically updates the FAT mapper from informations stored on device in case of miss.
 *****************************************************************************************
 * @ mapper	 : local pointer on the FAT mapper.
 * @ first	 : index of the first FATFS cluster allocated to the file.
 * @ page    : index of searched page in the file.
 * @ cluster : [out] pointer on buffer for the found FATFS cluster index.
 * @ return 0 if success / return EIO if FAT mapper miss cannot be solved.
 ****************************************************************************************/
error_t fatfs_get_cluster( struct mapper_s * mapper,
                           uint32_t          first_cluster,
                           uint32_t          searched_page,
                           uint32_t        * cluster );

/*****************************************************************************************
 * This function allocates memory for a FATFS inode, initializes it,
 * and link it to the VFS inode.
 *****************************************************************************************
 * @ inode   : local pointer on vfs_inode.
 * @ return 0 if success / return ENOMEM if error. 
 ****************************************************************************************/
error_t fatfs_inode_create( struct vfs_inode_s * inode );

/*****************************************************************************************
 * This function releases memory allocated for a FATFS inode.
 *****************************************************************************************
 * @ inode   : local pointer on vfs_inode.
 ****************************************************************************************/
void fatfs_inode_destroy( struct vfs_inode_s * inode );

/*****************************************************************************************
 * This function allocates memory for a FATFS context, initialises it, 
 * and link it to the local VFS context.
 *****************************************************************************************
 * @ inode   : local pointer on VFS context.
 * @ return 0 if success / return ENOMEM if error. 
 ****************************************************************************************/
error_t fatfs_ctx_create( struct vfs_ctx_s * ctx );

/*****************************************************************************************
 * This function releases memory allocated for a FATFS context.
 *****************************************************************************************
 * @ ctx   : local pointer on VFS context.
 ****************************************************************************************/
void fatfs_ctx_destroy( struct vfs_ctx_s * ctx );

/*****************************************************************************************
 * This function moves a page from the mapper to the FATFS file system.
 * It must be called by a thread running in cluster containing the mapper.
 * The pointer on the mapper and the page index in file are supposed to be registered
 * in the page descriptor. 
 *****************************************************************************************
 * @ page    : local pointer on page descriptor.
 * @ return 0 if success / return EIO if error. 
 ****************************************************************************************/
error_t fatfs_write_page( struct page_s * page );

/*****************************************************************************************
 * This function moves a page from the FATFS file system on device to the mapper.
 * It must be called by a thread running in cluster containing the mapper.
 * The pointer on the mapper and the page index in file are supposed to be registered
 * in the page descriptor. 
 *****************************************************************************************
 * @ page    : local pointer on page descriptor.
 * @ return 0 if success / return EIO if error. 
 ****************************************************************************************/
error_t fatfs_read_page( struct page_s * page );


#endif	/* _FATFS_H_ */
