Ignore:
Timestamp:
Dec 3, 2018, 12:15:53 PM (5 years ago)
Author:
alain
Message:

Improve the FAT32 file system to support cat, rm, cp commands.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/fs/fatfs.c

    r568 r602  
    22 * fatfs.c - FATFS file system API implementation.
    33 *
    4  * Author    Alain Greiner (2016,2017)
     4 * Author    Alain Greiner (2016,2017,2018)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    4242//////////////////////////////////////////////////////////////////////////////////////////
    4343
    44 extern vfs_ctx_t          fs_context[FS_TYPES_NR];   // allocated in vfs.c file
    45 
    46 //////////////////////////////////////////////////////////////////////////////////////////
    47 //              FATFS specific and static functions
     44extern vfs_ctx_t     fs_context[FS_TYPES_NR];   // allocated in kernel_init.c file
     45
     46//////////////////////////////////////////////////////////////////////////////////////////
     47//              FATFS specific static functions
    4848//////////////////////////////////////////////////////////////////////////////////////////
    4949
     
    8989    uint32_t res  = 0;
    9090
    91     if ( little_endian)
     91    if ( little_endian )
    9292    {
    9393        for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];
    9494    }
    95     else
     95    else // big_endian
    9696    {
    9797        for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];
     
    100100
    101101}  // end fatfs_get_record()
     102
     103//////////////////////////////////////////////////////////////////////////////////////////
     104// This function writes one, two, or four bytes from a 32 bits integer to a memory buffer,
     105// taking into account endianness.
     106//////////////////////////////////////////////////////////////////////////////////////////
     107// @ offset        : first byte of record in buffer.
     108// @ size          : record length in bytes (1/2/4).
     109// @ buffer        : pointer on buffer base.
     110// @ little endian : the most significant byte has the highest address when true.
     111// @ return the integer value in a 32 bits word.
     112//////////////////////////////////////////////////////////////////////////////////////////
     113static void fatfs_set_record( uint32_t    offset,
     114                              uint32_t    size,
     115                              uint8_t   * buffer,
     116                              uint32_t    little_endian,
     117                              uint32_t    value )
     118{
     119    uint32_t n;
     120
     121    if ( little_endian )
     122    {
     123        for( n = size ; n > 0 ; n-- ) buffer[offset+n-1] = (uint8_t)(value>>((n-1)<<3));
     124    }
     125    else // big_endian
     126    {
     127        for( n = 0 ; n < size ; n++ ) buffer[offset+n] = (uint8_t)(value>>((size-1-n)<<3));
     128    }
     129
     130}  // end fatfs_set_record()
    102131
    103132//////////////////////////////////////////////////////////////////////////////////////////
     
    136165
    137166    name[j] = '\0';
    138 }
     167
     168}  // fatfs_get_name_from_short()
    139169
    140170//////////////////////////////////////////////////////////////////////////////////////////
     
    213243    name[name_offset] = 0;
    214244
    215 } // end get_name_from_long()
     245} // end fatfs_get_name_from_long()
     246
     247//////////////////////////////////////////////////////////////////////////////////////////
     248// This static function analyse the <name> input argument, and returns in other
     249// output arguments various informations required to store the name in FATFS directory.
     250// The <name> length cannot be larger than 31 characters :
     251// - Short name (less than 13 characters) require 1 LFN entry.
     252// - Medium names (from 14 to 26 characters require 2 LFN entries.
     253// - Large names (up to 31 characters) require 3 LFN entries.
     254//////////////////////////////////////////////////////////////////////////////////////////
     255// @ name     : [in]  complete directory entry name.
     256// @ length   : [out] total number of characters in name.
     257// @ nb_lfn   : [out] number of LFN entries required to store the name.
     258// @ sfn      : [out] a legal SFN name extracted from name / upper case and 8-3 format.
     259// @ checksum : [out] checksum to be stored in SFN.
     260// @ returns 0 on success / returns 1 if the name length is larger than 31 characters.
     261//////////////////////////////////////////////////////////////////////////////////////////
     262static error_t fatfs_name_format( const char  * name,
     263                                  uint32_t    * length,
     264                                  uint32_t    * nb_lfn,
     265                                  char        * sfn,
     266                                  uint8_t     * checksum )
     267{
     268    // compute name length
     269    uint32_t name_length = strlen( name );
     270    *length = name_length;
     271
     272    uint32_t suffix_length = 0;
     273    uint32_t prefix_length = 0;
     274    uint32_t dot_found     = 0;
     275    uint32_t i;
     276
     277    // compute prefix and suffix length
     278    // only the last '.' is taken into account
     279    for ( i=0 ; i<name_length ; i++ )
     280    {
     281        if (name[i] == '.' )
     282        {
     283            if ( dot_found )
     284            {
     285                prefix_length += suffix_length + 1;
     286                suffix_length =  0;
     287            }
     288            else
     289            {
     290                dot_found = 1;
     291            }
     292        }
     293        else
     294        {
     295            if ( dot_found)  suffix_length++;
     296            else             prefix_length++;
     297        }
     298    }
     299
     300    // build SFN prefix (8bits)
     301    if (prefix_length <= 8)
     302    {
     303        for( i=0 ; i<8 ; i++)
     304        {
     305            if ( i<prefix_length ) sfn[i] = to_upper( name[i] );
     306            else                   sfn[i] = 0x20;
     307        }
     308    }
     309    else
     310    {
     311        for( i=0 ; i<6 ; i++)
     312        {
     313            sfn[i] = to_upper( name[i] );
     314        }
     315        sfn[6] = 0x7E;
     316        sfn[7] = 0x31;
     317    }
     318
     319    // build SFN suffix (3 bits)
     320    if ( suffix_length == 0 )
     321    {
     322        sfn[8]  = 0x20;
     323        sfn[9]  = 0x20;
     324        sfn[10] = 0x20;
     325    }
     326    else if ( suffix_length == 1 )
     327    {
     328        sfn[8]  = to_upper( name[name_length-1] );
     329        sfn[9]  = 0x20;
     330        sfn[10] = 0x20;
     331    }
     332    else if ( suffix_length == 2 )
     333    {
     334        sfn[8]  = to_upper( name[name_length-2] );
     335        sfn[9]  = to_upper( name[name_length-1] );
     336        sfn[10] = 0x20;
     337    }
     338    else
     339    {
     340        sfn[8]  = to_upper( name[name_length-suffix_length] );
     341        sfn[9]  = to_upper( name[name_length-suffix_length+1] );
     342        sfn[10] = to_upper( name[name_length-suffix_length+2] );
     343    }
     344
     345    // compute 8 bits checksum
     346    uint8_t sum = 0;
     347    for ( i=0 ; i<11 ; i++ )
     348    {
     349        sum = (((sum & 0x01)<<7) | ((sum & 0xFE)>>1)) + sfn[i];
     350    }
     351    *checksum = sum;
     352
     353    // set nb_lfn and length values
     354    if      ( name_length <= 13 )
     355    {
     356        *nb_lfn  = 1;
     357        return 0;
     358    }
     359    else if ( name_length <= 26 )
     360    {
     361        *nb_lfn  = 2;
     362        return 0;
     363    }
     364    else if ( name_length <= 31 )
     365    {
     366        *nb_lfn  = 3;
     367        return 0;
     368    }
     369    else
     370    {
     371        return 1;
     372    }
     373}   // end fatfs_name_format() 
     374
     375//////////////////////////////////////////////////////////////////////////////////////////
     376// This static function - atomically - decrements "free_clusters", and updates
     377// the "free_cluster_hint" shared variables in the FATFS context in the FAT cluster.
     378// It scan the FAT to find the first free slot larger than the <cluster> argument,
     379// and set "free_cluster_hint" <= (free - 1).
     380//
     381// WARNING : The free_lock protecting exclusive access to these variables
     382//           must be taken by the calling function.
     383//////////////////////////////////////////////////////////////////////////////////////////
     384// @ cluster     : recently allocated cluster index in FAT.
     385//////////////////////////////////////////////////////////////////////////////////////////
     386static error_t fatfs_free_clusters_decrement( uint32_t  cluster )
     387{
     388    fatfs_ctx_t * loc_ctx;      // local pointer on local FATFS context
     389    fatfs_ctx_t * fat_ctx;      // local pointer on FATFS in cluster containing FAT mapper
     390    cxy_t         mapper_cxy;   // cluster identifier for cluster containing FAT mapper
     391    xptr_t        mapper_xp;    // extended pointer on FAT mapper
     392    xptr_t        hint_xp;      // extended pointer on "free_cluster_hint" shared variable
     393    xptr_t        numb_xp;      // extended pointer on "free_clusters" shared variable
     394    uint32_t      numb;         // "free_clusters" variable current value
     395    uint32_t      page_id;      // page index in FAT mapper
     396    uint32_t      slot_id;      // slot index in one page of FAT (1024 slots per page)
     397    uint32_t      page_max;     // max number of pages in FAT mapper
     398    xptr_t        page_xp;      // extended pointer on current page in FAT mapper
     399    xptr_t        slot_xp;      // extended pointer on current slot in FAT mapper
     400
     401#if DEBUG_FATFS_FREE_CLUSTERS
     402uint32_t   cycle = (uint32_t)hal_get_cycles();
     403thread_t * this  = CURRENT_THREAD;
     404if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
     405printk("\n[%s] thread[%x,%x] enter for allocated cluster %x / cycle %d\n",
     406__FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
     407#endif
     408
     409    // get local pointer on local FATFS context
     410    loc_ctx = fs_context[FS_TYPE_FATFS].extend;
     411
     412    // get cluster containing FAT mapper
     413    mapper_xp  = loc_ctx->fat_mapper_xp;
     414    mapper_cxy = GET_CXY( mapper_xp );
     415
     416    // get local pointer on FATFS context in FAT cluster
     417    fat_ctx = hal_remote_lpt( XPTR( mapper_cxy , &fs_context[FS_TYPE_FATFS].extend ) );
     418
     419    // build extended pointers on free_clusters, and free_cluster_hint
     420    hint_xp = XPTR( mapper_cxy , &fat_ctx->free_cluster_hint );
     421    numb_xp = XPTR( mapper_cxy , &fat_ctx->free_clusters );
     422
     423    // update "free_clusters"
     424    numb = hal_remote_l32( numb_xp );
     425    hal_remote_s32( numb_xp , numb - 1 );
     426
     427    // scan FAT mapper to find the first free slot > cluster
     428    // and update "free_cluster_hint" as (free - 1)
     429    page_id  = (cluster + 1) >> 10;
     430    slot_id  = (cluster + 1) & 0x3FF;
     431    page_max = (loc_ctx->fat_sectors_count >> 3);
     432
     433    // scan FAT mapper / loop on pages
     434    while ( page_id < page_max )           
     435    {
     436        // get current page from mapper
     437        page_xp = mapper_remote_get_page( mapper_xp , page_id );
     438
     439        if( page_xp == XPTR_NULL )
     440        {
     441            printk("\n[ERROR] in %s : cannot access FAT mapper\n", __FUNCTION__ );
     442            return -1;
     443        }
     444
     445        // scan FAT mapper / loop on slots
     446        while ( slot_id < 1024 )
     447        {
     448            // get extended pointer on current slot
     449            slot_xp = ppm_page2base( page_xp ) + (slot_id << 2);
     450
     451            // test FAT slot value
     452            if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER )
     453            {
     454                // update "free_cluster_hint" <= (free - 1)
     455                hal_remote_s32( hint_xp , (page_id << 10) + slot_id - 1 );
     456
     457#if DEBUG_FATFS_FREE_CLUSTERS
     458cycle = (uint32_t)hal_get_cycles();
     459if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
     460printk("\n[%s] thread[%x,%x] exit / hint %x / free_clusters %x / cycle %d\n",
     461__FUNCTION__, this->process->pid, this->trdid,
     462hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle );
     463#endif
     464                return 0;
     465            }
     466
     467            // increment  slot_id
     468            slot_id++;
     469
     470        }  // end loop on slots
     471
     472        // update loop variables
     473        page_id++;
     474        slot_id = 0;
     475
     476    }  // end loop on pages
     477
     478    // return error if no free cluster found
     479    printk("\n[ERROR] in %s : No free cluster found\n", __FUNCTION__ );
     480    return -1;
     481   
     482}  // end fatfs_free_clusters_decrement()
     483
     484//////////////////////////////////////////////////////////////////////////////////////////
     485// This static function atomically increments <free_clusters>, and updates
     486// the <free_cluster_hint> shared variables in the FATFS context in the FAT cluster.
     487// If the released cluster index is smaller than the current (hint + 1) value,
     488// it set "free_cluster_hint" <= cluster - 1.
     489//
     490// WARNING : The free_lock protecting exclusive access to these variables
     491//           must be taken by the calling function.
     492//////////////////////////////////////////////////////////////////////////////////////////
     493// @ cluster     : recently released cluster index in FAT.
     494//////////////////////////////////////////////////////////////////////////////////////////
     495static void fatfs_free_clusters_increment( uint32_t  cluster )
     496{
     497    fatfs_ctx_t * loc_ctx;      // local pointer on local FATFS context
     498    fatfs_ctx_t * fat_ctx;      // local pointer on FATFS in cluster containing FAT mapper
     499    cxy_t         fat_cxy;      // cluster identifier for cluster containing FAT mapper
     500    xptr_t        hint_xp;      // extended pointer on "free_cluster_hint" shared variable
     501    xptr_t        numb_xp;      // extended pointer on "free_clusters" shared variable
     502    uint32_t      hint;         // "free_cluster_hint" variable current value
     503    uint32_t      numb;         // "free_clusters" variable current value
     504
     505    // get local pointer on local FATFS context
     506    loc_ctx = fs_context[FS_TYPE_FATFS].extend;
     507
     508    // get cluster containing FAT mapper
     509    fat_cxy = GET_CXY( loc_ctx->fat_mapper_xp );
     510
     511    // get local pointer on FATFS context in FAT cluster
     512    fat_ctx = hal_remote_lpt( XPTR( fat_cxy , &fs_context[FS_TYPE_FATFS].extend ) );
     513
     514    // build extended pointers free_lock, free_clusters, and free_cluster_hint
     515    hint_xp = XPTR( fat_cxy , &fat_ctx->free_cluster_hint );
     516    numb_xp = XPTR( fat_cxy , &fat_ctx->free_clusters );
     517
     518    // get current value of free_cluster_hint and free_clusters
     519    hint = hal_remote_l32( hint_xp );
     520    numb = hal_remote_l32( numb_xp );
     521
     522    // update free_cluster_hint if required
     523    if ( cluster < (hint + 1) ) hal_remote_s32( hint_xp , (cluster - 1) );
     524
     525    // update free_clusters
     526    hal_remote_s32( numb_xp , numb + 1 );
     527
     528#if DEBUG_FATFS_FREE_CLUSTERS
     529thread_t * this = CURRENT_THREAD;
     530if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
     531printk("\n[%s] thread[%x,%x] updates free cluster info : hint %x / number %x\n",
     532__FUNCTION__, this->process->pid, this->trdid,
     533hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) );
     534#endif
     535
     536}  // end fatfs_free_clusters_increment()
     537
     538//////////////////////////////////////////////////////////////////////////////////////////
     539// This recursive function is called by the generic function fatfs_release_all_clusters()
     540// It release all clusters allocated to a given inode in the FAT mapper.
     541// The removal is done in reverse order of the linked list (from last to first).
     542// It does NOT update the FS on the IOC device.
     543//////////////////////////////////////////////////////////////////////////////////////////
     544// @ fat_mapper_xp : extended pointer on FAT mapper.
     545// @ cluster       : cluster index in FAT.
     546// @ return 0 if success / return -1 if error (cannot access FAT)
     547//////////////////////////////////////////////////////////////////////////////////////////
     548static error_t fatfs_recursive_release( xptr_t    fat_mapper_xp,
     549                                        uint32_t  cluster )
     550{
     551    uint32_t next;
     552
     553    // get next cluster from FAT mapper
     554    if ( mapper_remote_get_32( fat_mapper_xp , cluster , &next ) ) return -1;
     555
     556#if (DEBUG_FATFS_RELEASE_INODE & 1)
     557thread_t * this = CURRENT_THREAD;
     558if ( DEBUG_FATFS_RELEASE_INODE < (uint32_t)hal_get_cycles() )
     559printk("\n[%s] thread[%x,%x] access FAT for cluster %x / next %x\n",
     560__FUNCTION__, this->process->pid, this->trdid, cluster, next );
     561#endif
     562
     563    if ( next < END_OF_CHAIN_CLUSTER_MIN )  // non terminal case
     564    {
     565        // call fatfs_recursive_release() on next cluster
     566        if ( fatfs_recursive_release( fat_mapper_xp , next ) ) return -1;
     567    }       
     568
     569    // update current cluster in FAT mapper
     570    if ( mapper_remote_set_32( fat_mapper_xp, cluster , FREE_CLUSTER ) ) return -1;
     571
     572    // Update free_cluster_hint and free_clusters in FAT context
     573    fatfs_free_clusters_increment( cluster );
     574
     575    return 0;
     576
     577}  // end fatfs_recursive_release()
    216578
    217579
     
    220582//////////////////////////////////////////////////////////////////////////////////////////
    221583
    222 //////////////////////////////////////////////////////////////////////////////////////////
     584//////////////////////////////
    223585void fatfs_ctx_display( void )
    224586{
     587    // get pointer on local FATFS context
    225588    vfs_ctx_t   * vfs_ctx   = &fs_context[FS_TYPE_FATFS];
    226589    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
    227590
    228591    printk("\n*** FAT context ***\n"
    229            "- fat_sectors      = %d\n"
    230            "- sector size      = %d\n"
    231            "- cluster size     = %d\n"
    232            "- fat_first_lba    = %d\n"
    233            "- data_first_lba   = %d\n"
    234            "- root_dir_cluster = %d\n"
    235            "- mapper_xp        = %l\n",
     592           "- fat_sectors       = %d\n"
     593           "- sector size       = %d\n"
     594           "- cluster size      = %d\n"
     595           "- fat_first_lba     = %d\n"
     596           "- data_first_lba    = %d\n"
     597           "- root_dir_cluster  = %d\n"
     598           "- free_clusters     = %d\n"
     599           "- free_cluster_hint = %d\n"
     600           "- fat_mapper_xp     = %l\n",
    236601           fatfs_ctx->fat_sectors_count,
    237602           fatfs_ctx->bytes_per_sector,
     
    240605           fatfs_ctx->cluster_begin_lba,
    241606           fatfs_ctx->root_dir_cluster,
     607           fatfs_ctx->free_clusters,
     608           fatfs_ctx->free_cluster_hint,
    242609           fatfs_ctx->fat_mapper_xp );
    243 }
    244 
    245 /////////////////////////////////////////////
    246 error_t fatfs_get_cluster( mapper_t * mapper,
    247                            uint32_t   first_cluster_id,
     610
     611}  // end fatfs_ctx_display()
     612
     613//////////////////////////////////////////
     614void fatfs_display_fat( uint32_t  page_id,
     615                        uint32_t  nentries )
     616{
     617    uint32_t line;
     618    uint32_t maxline;
     619
     620    // copute numner of lines to display
     621    maxline = nentries >> 3;
     622    if( nentries & 0x7 ) maxline++;
     623
     624    // get pointer on local FATFS context
     625    vfs_ctx_t   * vfs_ctx   = &fs_context[FS_TYPE_FATFS];
     626    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
     627
     628    // get extended pointer on FAT mapper
     629    xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp;
     630
     631    // get extended pointer and cluster of FAT mapper requested page
     632    xptr_t     page_xp  = mapper_remote_get_page( fat_mapper_xp , page_id );
     633
     634    // get extended pointer on requested page base
     635    xptr_t     base_xp  = ppm_page2base( page_xp );
     636
     637    printk("\n***** FAT content / page %d *****\n", page_id );
     638    for( line = 0 ; line < maxline ; line++ )
     639    {
     640        printk("%x : %X | %X | %X | %X | %X | %X | %X | %X\n", (line<<3),
     641        hal_remote_l32( base_xp + ((line<<5)      ) ),
     642        hal_remote_l32( base_xp + ((line<<5) + 4  ) ),
     643        hal_remote_l32( base_xp + ((line<<5) + 8  ) ),
     644        hal_remote_l32( base_xp + ((line<<5) + 12 ) ),
     645        hal_remote_l32( base_xp + ((line<<5) + 16 ) ),
     646        hal_remote_l32( base_xp + ((line<<5) + 20 ) ),
     647        hal_remote_l32( base_xp + ((line<<5) + 24 ) ),
     648        hal_remote_l32( base_xp + ((line<<5) + 28 ) ) );
     649    }
     650
     651}  // end fatfs_display_fat()
     652
     653///////////////////////////////////////////////////////
     654error_t fatfs_get_cluster( uint32_t   first_cluster_id,
    248655                           uint32_t   searched_page_index,
    249656                           uint32_t * searched_cluster_id )
    250657{
    251     page_t   * current_page_desc;      // pointer on current page descriptor
    252     uint32_t * current_page_buffer;    // pointer on current page (array of uint32_t)
     658    xptr_t     current_page_xp;        // pointer on current page descriptor
     659    uint32_t * buffer;                 // pointer on current page (array of uint32_t)
    253660    uint32_t   current_page_index;     // index of current page in FAT
    254661    uint32_t   current_page_offset;    // offset of slot in current page
     
    256663    uint32_t   next_cluster_id;        // content of current FAT slot
    257664
    258     assert( (searched_page_index > 0) ,
    259     "no FAT access required for first page\n");
     665assert( (searched_page_index > 0) ,
     666"no FAT access required for first page\n");
    260667
    261668#if DEBUG_FATFS_GET_CLUSTER
    262 uint32_t cycle = (uint32_t)hal_get_cycles();
     669uint32_t   cycle = (uint32_t)hal_get_cycles();
     670thread_t * this  = CURRENT_THREAD;
    263671if( DEBUG_FATFS_GET_CLUSTER < cycle )
    264 printk("\n[DBG] %s : thread %x enter / first_cluster_id %d / searched_index / cycle %d\n",
    265 __FUNCTION__, CURRENT_THREAD, first_cluster_id, searched_page_index, cycle );
    266 #endif
    267 
    268     // get number of FAT slots per page
    269     uint32_t slots_per_page = CONFIG_PPM_PAGE_SIZE >> 2;
    270 
    271     // initialize loop variable
    272     current_page_index  = first_cluster_id / slots_per_page;
    273     current_page_offset = first_cluster_id % slots_per_page;
     672printk("\n[%s] thread[%x,%x] enter / first_cluster_id %d / searched_index / cycle %d\n",
     673__FUNCTION__, this->process->pid, this->trdid, first_cluster_id, searched_page_index, cycle );
     674#endif
     675
     676    // get local pointer on local FATFS context
     677    fatfs_ctx_t * ctx = fs_context[FS_TYPE_FATFS].extend;
     678
     679    // get extended pointer and cluster on FAT mapper
     680    xptr_t mapper_xp  = ctx->fat_mapper_xp;
     681    cxy_t  mapper_cxy = GET_CXY( mapper_xp );
     682
     683    // initialize loop variable (1024 slots per page)
     684    current_page_index  = first_cluster_id >> 10;
     685    current_page_offset = first_cluster_id & 0x3FF;
    274686    page_count_in_file  = 0;
    275687    next_cluster_id     = 0xFFFFFFFF;
     
    279691    {
    280692        // get pointer on current page descriptor
    281         current_page_desc = mapper_get_page( mapper , current_page_index );
    282 
    283         if( current_page_desc == NULL ) return EIO;
     693        current_page_xp = mapper_remote_get_page( mapper_xp , current_page_index );
     694
     695        if( current_page_xp == XPTR_NULL )
     696        {
     697            // TODO
     698            return -1;
     699        }
    284700
    285701        // get pointer on buffer for current page
    286         xptr_t base_xp = ppm_page2base( XPTR( local_cxy , current_page_desc ) );
    287         current_page_buffer = (uint32_t *)GET_PTR( base_xp );
     702        xptr_t base_xp = ppm_page2base( current_page_xp );
     703        buffer = (uint32_t *)GET_PTR( base_xp );
    288704
    289705        // get FAT slot content
    290         next_cluster_id = current_page_buffer[current_page_offset];
     706        next_cluster_id = hal_remote_l32( XPTR( mapper_cxy , &buffer[current_page_offset] ) );
    291707
    292708#if (DEBUG_FATFS_GET_CLUSTER & 1)
    293709if( DEBUG_FATFS_GET_CLUSTER < cycle )
    294 printk("\n[DBG] %s : traverse FAT / current_page_index = %d\n"
     710printk("\n[%s] traverse FAT / current_page_index = %d\n"
    295711"current_page_offset = %d / next_cluster_id = %d\n",
    296712__FUNCTION__, current_page_index, current_page_offset , next_cluster_id );
     
    298714
    299715        // update loop variables
    300         current_page_index  = next_cluster_id / slots_per_page;
    301         current_page_offset = next_cluster_id % slots_per_page;
     716        current_page_index  = next_cluster_id >> 10;
     717        current_page_offset = next_cluster_id & 0x3FF;
    302718        page_count_in_file++;
    303719    }
    304720
    305     if( next_cluster_id == 0xFFFFFFFF ) return EIO;
     721    if( next_cluster_id == 0xFFFFFFFF ) return -1;
    306722   
    307723#if DEBUG_FATFS_GET_CLUSTER
    308724cycle = (uint32_t)hal_get_cycles();
    309725if( DEBUG_FATFS_GET_CLUSTER < cycle )
    310 printk("\n[DBG] %s : thread %x exit / searched_cluster_id = %d / cycle %d\n",
    311 __FUNCTION__, CURRENT_THREAD, next_cluster_id / cycle );
     726printk("\n[%s] thread[%x,%x] exit / searched_cluster_id = %d / cycle %d\n",
     727__FUNCTION__, this->process->pid, this->trdid, next_cluster_id / cycle );
    312728#endif
    313729
     
    320736
    321737///////////////////////////////////////////////////////////////////////////////////////
    322 // Generic API : the following functions are called by the kernel (VFS)
     738// Generic API : the following functions are called by the kernel VFS
    323739//               and must be defined by all supported file systems.
    324740///////////////////////////////////////////////////////////////////////////////////////
     
    342758    uint8_t     * buffer;
    343759
    344 #if DEBUG_FATFS_INIT
     760#if DEBUG_FATFS_CTX_INIT
    345761uint32_t cycle = (uint32_t)hal_get_cycles();
    346 if( DEBUG_FATFS_INIT < cycle )
    347 printk("\n[DBG] %s : thread %x enter for fatfs_ctx = %x / cycle %d\n",
    348 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx , cycle );
    349 #endif
    350 
    351     assert( (fatfs_ctx != NULL) ,
    352     "cannot allocate memory for FATFS context\n" );
     762if( DEBUG_FATFS_CTX_INIT < cycle )
     763printk("\n[%s] thread[%x,%x] enter for fatfs_ctx = %x / cycle %d\n",
     764__FUNCTION__ , this->process->pid, this->trdid, fatfs_ctx , cycle );
     765#endif
     766
     767// check argument
     768assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL\n" );
     769
     770// check only cluster 0 does FATFS init
     771assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS\n");
    353772
    354773    // allocate a 512 bytes buffer to store the boot record
     
    357776        buffer      = (uint8_t *)kmem_alloc( &req );
    358777
    359     assert( (buffer != NULL) ,
    360     "cannot allocate memory for 512 bytes buffer\n" );
     778    if( buffer == NULL )
     779    {
     780        printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ );
     781        hal_core_sleep();
     782    }
    361783     
    362     // load the boot record from device
    363     // using a synchronous access to IOC device 
     784    // load the BOOT record from device
    364785    error = dev_ioc_sync_read( buffer , 0 , 1 );
    365786
    366     assert( (error == 0) ,
    367     "cannot access boot record\n" );
    368 
    369 #if (DEBUG_FATFS_INIT & 0x1)
    370 if( DEBUG_FATFS_INIT < cycle )
     787    if ( error )
     788    {
     789        printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ );
     790        hal_core_sleep();
     791    }
     792
     793#if (DEBUG_FATFS_CTX_INIT & 0x1)
     794if( DEBUG_FATFS_CTX_INIT < cycle )
    371795{
    372796    uint32_t   line;
     
    387811#endif
    388812
    389     // check sector size from boot record
     813    // get sector size from boot record
    390814    uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer , 1 );
    391 
    392     assert( (sector_size == 512) ,
    393             "sector size must be 512 bytes\n" );
    394 
    395     // check cluster size from boot record
     815    if ( sector_size != 512 )
     816    {
     817        printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ );
     818        hal_core_sleep();
     819    }
     820
     821    // get cluster size from boot record
    396822    uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer , 1 );
    397 
    398     assert( (nb_sectors == 8) ,
    399     "cluster size must be 8 sectors\n" );
    400 
    401     // check number of FAT copies from boot record
     823    if ( nb_sectors != 8 )
     824    {
     825        printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ );
     826        hal_core_sleep();
     827    }
     828
     829    // get number of FAT copies from boot record
    402830    uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer , 1 );
    403 
    404     assert( (nb_fats == 1) ,
    405     "number of FAT copies must be 1\n" );
    406 
    407     // get & check number of sectors in FAT from boot record
     831    if ( nb_fats != 1 )
     832    {
     833        printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ );
     834        hal_core_sleep();
     835    }
     836
     837    // get number of sectors in FAT from boot record
    408838    uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer , 1 );
    409 
    410     assert( ((fat_sectors & 0xF) == 0) ,
    411     "FAT not multiple of 16 sectors\n");
    412 
    413     // get and check root cluster from boot record
     839    if ( (fat_sectors & 0xF) != 0 )
     840    {
     841        printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ );
     842        hal_core_sleep();
     843    }
     844
     845    // get root cluster from boot record
    414846    uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer , 1 );
    415 
    416     assert( (root_cluster == 2) ,
    417     "root cluster index must be  2\n");
     847    if ( root_cluster != 2 )
     848    {
     849        printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ );
     850        hal_core_sleep();
     851    }
    418852
    419853    // get FAT lba from boot record
    420854    uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer , 1 );
     855
     856    // get FS_INFO sector lba from boot record
     857    uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer , 1 );
     858
     859    // load the FS_INFO record from device
     860    error = dev_ioc_sync_read( buffer , fs_info_lba , 1 );
     861
     862    if ( error )
     863    {
     864        printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ );
     865        hal_core_sleep();
     866    }
     867
     868    // get free clusters number from FS_INFO record
     869    uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer , 1 );
     870    if ( free_clusters >= fat_sectors << 7 )
     871    {
     872        printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ );
     873        hal_core_sleep();
     874    }
     875
     876    // get cluster hint from FS_INFO record
     877    uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer , 1 );
     878    if ( free_cluster_hint >= fat_sectors << 7 )
     879    {
     880        printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ );
     881        hal_core_sleep();
     882    }
    421883
    422884    // release the 512 bytes buffer
     
    427889    // allocate a mapper for the FAT itself
    428890    mapper_t * fat_mapper = mapper_create( FS_TYPE_FATFS );
    429 
    430     assert( (fat_mapper != NULL) ,
    431     "no memory for FAT mapper" );
     891    if ( fat_mapper == NULL )
     892    {
     893        printk("\n[PANIC] in %s : no memory for FAT mapper\n", __FUNCTION__ );
     894        hal_core_sleep();
     895    }
    432896
    433897    // WARNING : the inode field MUST be NULL for the FAT mapper
     
    441905    fatfs_ctx->cluster_begin_lba     = fat_lba + fat_sectors;
    442906    fatfs_ctx->root_dir_cluster      = 2;
    443     fatfs_ctx->last_allocated_sector = 0;    // TODO ???
    444     fatfs_ctx->last_allocated_index  = 0;    // TODO ???
    445907    fatfs_ctx->fat_mapper_xp         = XPTR( local_cxy , fat_mapper );
    446 
    447 #if DEBUG_FATFS_INIT
     908    fatfs_ctx->free_clusters         = free_clusters;
     909    fatfs_ctx->free_cluster_hint     = free_cluster_hint;
     910
     911    remote_queuelock_init( XPTR( local_cxy , &fatfs_ctx->free_lock ) , LOCK_FATFS_FREE );
     912
     913#if DEBUG_FATFS_CTX_INIT
    448914cycle = (uint32_t)hal_get_cycles();
    449 if( DEBUG_FATFS_INIT < cycle )
    450 printk("\n[DBG] %s : thread %x exit for fatfs_ctx = %x / cycle %d\n",
    451 __FUNCTION__ , CURRENT_THREAD , fatfs_ctx , cycle );
     915if( DEBUG_FATFS_CTX_INIT < cycle )
     916printk("\n[%s]  thread[%x,%x] exit for fatfs_ctx = %x / cycle %d\n",
     917__FUNCTION__, this->process->pid, this->trdid, fatfs_ctx, cycle );
    452918#endif
    453919
     
    463929}
    464930
    465 //////////////////////////////////////////////
    466 error_t fatfs_mapper_move_page( page_t * page,
    467                                 bool_t   to_mapper )
     931///////////////////////////////////////////////
     932error_t fatfs_add_dentry( vfs_inode_t  * inode,
     933                          vfs_dentry_t * dentry )
    468934{
    469935    error_t       error;
    470     vfs_inode_t * inode;
    471     mapper_t    * mapper;
    472     uint32_t      index;       // page index in mapper
    473     uint8_t     * buffer;      // page base address in mapper
    474     uint32_t      count;       // number of sectors in a page
    475     uint32_t      lba;         // block address on device
    476     fatfs_ctx_t * fatfs_ctx;   // pointer on local FATFS context
    477 
    478     // get pointer on mapper and page index from page descriptor
    479     mapper = page->mapper;
    480     index  = page->index;
    481 
    482     // get inode pointer from mapper
    483     inode = mapper->inode;
    484 
    485 #if DEBUG_FATFS_MOVE
    486 uint32_t cycle = (uint32_t)hal_get_cycles();
    487 if( DEBUG_FATFS_MOVE < cycle )
    488 printk("\n[DBG] %s : thread %x enter / page %d / inode %x / mapper %x / cycle %d\n",
    489 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle );
    490 #endif
    491 
    492     // get page base address
    493     xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
    494     buffer = (uint8_t *)GET_PTR( base_xp );
    495  
    496     // get number of sectors for one page (from FATFS context)
    497     fatfs_ctx = (fatfs_ctx_t *)fs_context[FS_TYPE_FATFS].extend;
    498     count = fatfs_ctx->sectors_per_cluster;
    499 
    500     // test FAT/normal inode
    501     if( inode == NULL )      // it is the FAT mapper
    502     {
    503         // get lba from page index
    504         lba = fatfs_ctx->fat_begin_lba + (count * index);
    505  
    506 #if (DEBUG_FATFS_MOVE & 0x1)
    507 if( DEBUG_FATFS_MOVE < cycle )
    508 printk("\n[DBG] %s : access FAT on device / lba = %d\n", __FUNCTION__ , lba );
    509 #endif
    510 
    511         // access device
    512         if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count );
    513         else            error = dev_ioc_write( buffer , lba , count );     
    514 
    515         if( error ) return EIO;
    516     }
    517     else                     // it is a normal inode mapper
    518     {
    519         uint32_t  searched_cluster_id;
    520 
    521         // get first_cluster_id from inode extension
    522         uint32_t  first_cluster_id = (uint32_t)(intptr_t)inode->extend;
    523 
    524         // compute cluster_id
    525         if( index == 0 )            // no need to access FAT mapper
     936    uint32_t      length;        // dentry name length
     937    uint32_t      nb_lfn;        // number or required LFN
     938    char          sfn[11];       // buffer for SFN name
     939    uint8_t       checksum;      // name checksum
     940    mapper_t    * mapper;        // loal pointer on parent inode mapper
     941    xptr_t        mapper_xp;     // extended pointer on parent inode mapper
     942    xptr_t        child_xp;      // extended pointer on child inode
     943    cxy_t         child_cxy;     // child inode cluster
     944    vfs_inode_t * child_ptr;     // child inode local pointer
     945    uint32_t      size;          // child inode size
     946    uint32_t      type;          // child inode type
     947    uint32_t      cluster;       // child inode cluster index
     948
     949#if DEBUG_FATFS_ADD_DENTRY
     950char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
     951uint32_t   cycle = (uint32_t)hal_get_cycles();
     952thread_t * this  = CURRENT_THREAD;
     953vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
     954if( DEBUG_FATFS_ADD_DENTRY < cycle )
     955printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
     956__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     957#endif
     958
     959// check arguments
     960assert( (inode != NULL) , "inode pointer is NULL\n" );
     961assert( (dentry != NULL) , "dentry pointer is NULL\n" );
     962assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" );
     963assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
     964 
     965    // get pointers on directory mapper
     966    mapper    = inode->mapper;
     967    mapper_xp = XPTR( local_cxy , mapper );
     968
     969    // get extended pointers on remote child inode
     970    child_xp  = dentry->child_xp;
     971    child_cxy = GET_CXY( child_xp );
     972    child_ptr = GET_PTR( child_xp );
     973
     974    // get relevant infos from child inode
     975    type    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
     976    size    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->size ) );
     977    cluster = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( child_cxy , &child_ptr->extend ) );
     978
     979    // analyse dentry name
     980    error = fatfs_name_format( dentry->name,
     981                               &length,
     982                               &nb_lfn,
     983                               sfn,
     984                               &checksum );
     985    if ( error )
     986    {
     987        printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ );
     988        return -1;
     989    }
     990                               
     991    // Search end of directory with two embedded loops:
     992    // - scan the pages in the mapper
     993    // - scan the entries in each page to find NO_MORE_ENTRY
     994
     995    xptr_t     page_xp;                 // extended pointer on page descriptor
     996    xptr_t     base_xp;                 // extended pointer on page base
     997    uint8_t  * base;                    // local pointer on page base (array of bytes)
     998    uint32_t   page_id = 0;             // page index in mapper
     999    uint32_t   offset  = 0;             // position in page
     1000    uint32_t   found   = 0;             // NO_MORE_ENTRY found
     1001
     1002    // loop on pages in mapper
     1003    while ( found == 0 )
     1004    {
     1005        // get extended pointer on page descriptor in mapper
     1006        page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     1007
     1008        if ( page_xp == XPTR_NULL )
    5261009        {
    527             searched_cluster_id = first_cluster_id;
     1010            printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
     1011            return -1;
    5281012        }
    529         else                        // FAT mapper access required
     1013       
     1014        // get pointer on page base
     1015        base_xp = ppm_page2base( page_xp );
     1016        base = GET_PTR( base_xp );
     1017
     1018        // loop on directory entries in this page
     1019        while ( (offset < 4096) && (found == 0) )
    5301020        {
    531             // get cluster and local pointer on FAT mapper
    532             xptr_t     fat_mapper_xp  = fatfs_ctx->fat_mapper_xp;
    533             cxy_t      fat_mapper_cxy = GET_CXY( fat_mapper_xp );
    534             mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );
    535 
    536             // access FAT mapper
    537             if( fat_mapper_cxy == local_cxy )    // FAT mapper is local
     1021            if ( fatfs_get_record( LDIR_ORD, (base + offset), 0 ) == NO_MORE_ENTRY )
    5381022            {
    539 
    540 #if (DEBUG_FATFS_MOVE & 0x1)
    541 if( DEBUG_FATFS_MOVE < cycle )
    542 printk("\n[DBG] %s : access local FAT mapper\n"
    543 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n",
    544 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index );
    545 #endif
    546                 error = fatfs_get_cluster( fat_mapper_ptr,
    547                                            first_cluster_id,
    548                                            index,
    549                                            &searched_cluster_id );
     1023                found = 1;
     1024            } 
     1025            else
     1026            {
     1027                offset = offset + 32;
    5501028            }
    551             else                                 // FAT mapper is remote
     1029        }  // end loop on entries
     1030
     1031        if ( found == 0 )
     1032        {
     1033            page_id++;
     1034            offset = 0;
     1035        }
     1036    }  // end loop on pages
     1037
     1038    // Modify the directory mapper: depending on the name length,
     1039    // the new child requires to write (3, 4, or 5) directory entries.
     1040    // To actually register the new child, we use a 5 steps FSM
     1041    // (one state per entry to be written), that is traversed as:
     1042    // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE
     1043    // At most two pages are modified:
     1044    // - the page containing the NO_MORE_ENTRY is always modified
     1045    // - the following page can be modified if the name spread on to pages.
     1046
     1047    char * name = dentry->name;
     1048
     1049    uint32_t step;          // FSM state
     1050
     1051    if      ( nb_lfn == 1 ) step = 3;
     1052    else if ( nb_lfn == 2 ) step = 4;
     1053    else if ( nb_lfn == 3 ) step = 5;
     1054   
     1055    uint8_t  * entry;       // pointer on directory entry to be written
     1056    uint32_t   i;           // byte index in one 32 bytes directory
     1057    uint32_t   c;           // character index in name
     1058
     1059    while ( step )   
     1060    {
     1061        // when the new child is split on two pages,
     1062        // we need to access a new page in mapper
     1063        if ( offset >= 4096 )
     1064        {
     1065            // copy the modified page to IOC device
     1066            fatfs_move_page( page_xp , false );   
     1067
     1068            // get the next page in FAT mapper
     1069            page_xp  = mapper_remote_get_page( mapper_xp , page_id + 1 );
     1070
     1071            if ( page_xp == XPTR_NULL )
    5521072            {
    553 
    554 #if (DEBUG_FATFS_MOVE & 0x1)
    555 if( DEBUG_FATFS_MOVE < cycle )
    556 printk("\n[DBG] %s : access remote FAT mapper\n"
    557 "fat_mapper_cxy = %x / fat_mapper_ptr = %x / first_cluster_id = %d / index = %d\n",
    558 __FUNCTION__ , fat_mapper_cxy , fat_mapper_ptr , first_cluster_id , index );
    559 #endif
    560                 rpc_fatfs_get_cluster_client( fat_mapper_cxy,
    561                                               fat_mapper_ptr,
    562                                               first_cluster_id,
    563                                               index,
    564                                               &searched_cluster_id,
    565                                               &error );
     1073                printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
     1074                return -1;
    5661075            }
    567 
    568             if( error )  return EIO;
     1076       
     1077            // get pointer on page base
     1078            base_xp = ppm_page2base( page_xp );
     1079            base = GET_PTR( base_xp );
     1080           
     1081            // update offset
     1082            offset = 0;
    5691083        }
    5701084
    571 #if (DEBUG_FATFS_MOVE & 0x1)
    572 if( DEBUG_FATFS_MOVE < cycle )
    573 printk("\n[DBG] %s : access device for inode %x / cluster_id %d\n",
    574 __FUNCTION__ , inode , searched_cluster_id );
    575 #endif
    576 
    577         // get lba from cluster_id
    578         lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id );
    579 
    580         // access device
    581         if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , count );
    582         else            error = dev_ioc_write( buffer , lba , count );     
    583 
    584         if( error ) return EIO;
    585     }
    586 
    587 #if DEBUG_FATFS_MOVE
     1085        // compute directory entry address
     1086        entry = base + offset;
     1087
     1088#if (DEBUG_FATFS_ADD_DENTRY & 1)
     1089if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1090printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d\n",
     1091__FUNCTION__, step, offset, nb_lfn );
     1092#endif
     1093
     1094        // write 32 bytes (one directory entry) per iteration
     1095        switch ( step )
     1096        {
     1097            case 5:   // write LFN3 entry
     1098            {
     1099                c = 26;
     1100                // scan the 32 bytes in dir_entry
     1101                for ( i = 0 ; i < 32 ; i++ )
     1102                {
     1103                    if (i == 0)
     1104                    {
     1105                        if ( nb_lfn == 3) entry[i] = 0x43;
     1106                        else              entry[i] = 0x03;
     1107                    }
     1108                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1109                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1110                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1111                              ( c < length ) )
     1112                    {
     1113                                          entry[i] = name[c];
     1114                                          c++;
     1115                    }
     1116                    else if (i == 11)     entry[i] = 0x0F;
     1117                    else if (i == 13)     entry[i] = checksum;
     1118                    else                  entry[i] = 0x00;
     1119                }
     1120                step--;
     1121                break;
     1122            }
     1123            case 4:   // write LFN2 entry 
     1124            {
     1125                c = 13;
     1126                // scan the 32 bytes in dir_entry
     1127                for ( i = 0 ; i < 32 ; i++ )
     1128                {
     1129                    if (i == 0)
     1130                    {
     1131                        if ( nb_lfn == 2) entry[i] = 0x42;
     1132                        else              entry[i] = 0x02;
     1133                    }
     1134                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1135                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1136                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1137                              ( c < length ) )
     1138                    {
     1139                                          entry[i] = name[c];
     1140                                          c++;
     1141                    }
     1142                    else if (i == 11)     entry[i] = 0x0F;
     1143                    else if (i == 13)     entry[i] = checksum;
     1144                    else                  entry[i] = 0x00;
     1145                }
     1146                step--;
     1147                break;
     1148            }
     1149            case 3:   // Write LFN1 entry   
     1150            {
     1151                c = 0;
     1152                // scan the 32 bytes in dir_entry
     1153                for ( i = 0 ; i < 32 ; i++ )
     1154                {
     1155                    if (i == 0)
     1156                    {
     1157                        if ( nb_lfn == 1) entry[i] = 0x41;
     1158                        else              entry[i] = 0x01;
     1159                    }
     1160                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     1161                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     1162                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     1163                              ( c < length ) )
     1164                    {
     1165                                          entry[i] = name[c];
     1166                                          c++;
     1167                    }
     1168                    else if (i == 11)     entry[i] = 0x0F;
     1169                    else if (i == 13)     entry[i] = checksum;
     1170                    else                  entry[i] = 0x00;
     1171                }
     1172                step--;
     1173                break;
     1174            }
     1175            case 2:   // write NORMAL entry     
     1176            {
     1177                // scan the 32 bytes in dir_entry
     1178                for ( i = 0 ; i < 32 ; i++ )
     1179                {
     1180                    if      ( i < 11 )                              // 8.3 SFN
     1181                    {
     1182                                          entry[i] = sfn[i];
     1183                    }
     1184                    else if (i == 11)                               // ATTR
     1185                    {
     1186                        if (type == INODE_TYPE_DIR)  entry[i] = 0x10;
     1187                        else                         entry[i] = 0x20;
     1188                    }
     1189                    else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2
     1190                    else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3
     1191                    else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0
     1192                    else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1
     1193                    else if (i == 28)     entry[i] = size>>0;       // size.B0
     1194                    else if (i == 29)     entry[i] = size>>8;       // size.B1
     1195                    else if (i == 30)     entry[i] = size>>16;      // size.B2
     1196                    else if (i == 31)     entry[i] = size>>24;      // size.B3
     1197                    else                  entry[i] = 0x00;
     1198                }
     1199
     1200                // update the "extend" field in dentry descriptor
     1201                dentry->extend = (void*)(intptr_t)(((page_id<<12) + offset)>>5);
     1202
     1203                step--;
     1204                break;
     1205            }
     1206            case 1:   // write NOMORE entry 
     1207            {
     1208                entry [0] = 0x00;
     1209                step--;
     1210                break;
     1211            }
     1212        } // end switch step
     1213
     1214        offset += 32;
     1215
     1216    } // exit while     
     1217
     1218    // copy the modified page to the IOC device
     1219    fatfs_move_page( page_xp , false );   
     1220
     1221#if DEBUG_FATFS_ADD_DENTRY
    5881222cycle = (uint32_t)hal_get_cycles();
    589 if( DEBUG_FATFS_MOVE < cycle )
    590 printk("\n[DBG] %s : thread %x exit / page %d / inode %x / mapper %x / cycle %d\n",
    591 __FUNCTION__ , CURRENT_THREAD , index , inode , mapper , cycle );
    592 #endif
    593 
    594 #if (DEBUG_FATFS_MOVE & 0x1)
    595 if( DEBUG_FATFS_MOVE < cycle )
    596 {
    597     uint32_t * tab = (uint32_t *)buffer;
    598     uint32_t line , word;
    599     printk("\n***** %s : First 64 words of loaded page\n", __FUNCTION__ );
    600     for( line = 0 ; line < 8 ; line++ )
    601     {
    602         printk("%X : ", line );
    603         for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] );
    604         printk("\n");
    605     }
    606 }
     1223if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1224printk("\n[%s]  thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
     1225__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    6071226#endif
    6081227
    6091228    return 0;
    6101229
    611 }  // end fatfs_mapper_move_page()
    612 
    613 /////////////////////////////////////////////////////
    614 error_t fatfs_inode_load( vfs_inode_t * parent_inode,
     1230}  // end fatfs_add_dentry()
     1231
     1232//////////////////////////////////////////////////
     1233error_t fatfs_remove_dentry( vfs_inode_t  * inode,
     1234                             vfs_dentry_t * dentry )
     1235{
     1236    xptr_t     mapper_xp;  // extended pointer on mapper
     1237    mapper_t * mapper;     // local pointer on mapper
     1238    xptr_t     page_xp;    // extended pointer on mapper page descriptor
     1239    xptr_t     base_xp;    // extended pointer on mapper page base
     1240    uint8_t  * base;       // local pointer on mapper page base
     1241
     1242#if DEBUG_FATFS_REMOVE_DENTRY
     1243char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1244uint32_t   cycle = (uint32_t)hal_get_cycles();
     1245thread_t * this  = CURRENT_THREAD;
     1246vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
     1247if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     1248printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
     1249__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     1250#endif
     1251
     1252// check arguments
     1253assert( (inode != NULL) , "inode pointer is NULL\n" );
     1254assert( (dentry != NULL) , "dentry pointer is NULL\n" );
     1255assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" );
     1256assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
     1257
     1258    // get pointers on directory mapper
     1259    mapper    = inode->mapper;
     1260    mapper_xp = XPTR( local_cxy , mapper );
     1261
     1262    // compute number of LFN entries
     1263    uint32_t nb_lfn;
     1264    uint32_t name_length = strlen( dentry->name );
     1265
     1266    if      ( name_length <= 13 ) nb_lfn  = 1;
     1267    else if ( name_length <= 26 ) nb_lfn  = 2;
     1268    else                          nb_lfn  = 3;
     1269
     1270    // we must invalidate (2, 3 or 4) 32 bytes entries:
     1271    // the NORMAL entry (registered in dentry->extend) and all preceding LFN entries
     1272    // At most two pages are modified:
     1273    // - the page containing the NORMAL entry is always modified.
     1274    // - the preceding page is modified when the name spread on two pages.
     1275
     1276    // get 32 bytes directory entry index from dentry->extend
     1277    uint32_t  dentry_id  = (uint32_t)(intptr_t)dentry->extend;
     1278
     1279    // get page index and offset in parent directory mapper
     1280    uint32_t  page_id    = dentry_id >> 7;
     1281    uint32_t  offset     = (dentry_id & 0x7F)<<5;
     1282
     1283    // get extended pointer on page descriptor from parent directory mapper
     1284    page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     1285
     1286    if ( page_xp == XPTR_NULL )
     1287    {
     1288        printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
     1289        return -1;
     1290    }
     1291       
     1292    // get pointers on page base
     1293    base_xp = ppm_page2base( page_xp );
     1294    base    = GET_PTR( base_xp );
     1295
     1296    // invalidate NORMAL entry in directory cache
     1297    base[offset] = 0xE5;
     1298
     1299    // invalidate LFN entries
     1300    while ( nb_lfn )
     1301    {
     1302        if (offset == 0)  // we must load page (page_id - 1)
     1303        {
     1304
     1305// check page_id
     1306assert( (page_id > 0), "page_id and offset cannot be both 0\n" );
     1307
     1308            // copy the modified page to the IOC device
     1309            fatfs_move_page( page_xp , false );   
     1310
     1311            // get extended pointer on page descriptor from parent directory mapper
     1312            page_xp  = mapper_remote_get_page( mapper_xp , page_id );
     1313
     1314            if ( page_xp == XPTR_NULL )
     1315            {
     1316                printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
     1317                return -1;
     1318            }
     1319       
     1320            // get pointers on page base
     1321            base_xp = ppm_page2base( page_xp );
     1322            base    = GET_PTR( base_xp );
     1323
     1324            // update offset
     1325            offset = 4096;
     1326        }
     1327
     1328        offset = offset - 32;
     1329
     1330// check for LFN entry
     1331assert( (fatfs_get_record( DIR_ATTR, base + offset, 0 ) == ATTR_LONG_NAME_MASK ),
     1332"this directory entry must be a LFN\n");
     1333
     1334        // invalidate LFN entry
     1335        base[offset] = 0xE5;
     1336
     1337        nb_lfn--;
     1338    }     
     1339
     1340    // copy the modified page to the IOC device
     1341    fatfs_move_page( page_xp , false );   
     1342   
     1343
     1344#if DEBUG_FATFS_REMOVE_DENTRY
     1345cycle = (uint32_t)hal_get_cycles();
     1346if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     1347printk("\n[%s]  thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
     1348__FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     1349#endif
     1350
     1351    return 0;
     1352
     1353}  // end fatfs_remove_dentry
     1354
     1355////////////////////////////////////////////////////////////////
     1356error_t fatfs_child_init( vfs_inode_t * parent_inode,
    6151357                          char        * name,
    6161358                          xptr_t        child_inode_xp )
    6171359{
    6181360    // Two embedded loops:
    619     // - scan the parent mapper pages
     1361    // - scan the parent directory mapper pages
    6201362    // - scan the directory entries in each 4 Kbytes page
    6211363
    622 #if DEBUG_FATFS_LOAD
    623 uint32_t cycle = (uint32_t)hal_get_cycles();
    624 if( DEBUG_FATFS_LOAD < cycle )
    625 printk("\n[DBG] %s : thread %x enter for child <%s> in parent inode %x / cycle %d\n",
    626 __FUNCTION__ , CURRENT_THREAD , name , parent_inode , cycle );
    627 #endif
    628 
    629     mapper_t * mapper = parent_inode->mapper;
    630 
    631     assert( (mapper != NULL) , "parent mapper undefined\n");
     1364#if DEBUG_FATFS_CHILD_INIT
     1365char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1366uint32_t   cycle = (uint32_t)hal_get_cycles();
     1367thread_t * this  = CURRENT_THREAD;
     1368vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
     1369if( DEBUG_FATFS_CHILD_INIT < cycle )
     1370printk("\n[%s]  thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
     1371__FUNCTION__, this->process->pid, this->trdid, name , parent_name , cycle );
     1372#endif
     1373
     1374// check parent_inode and child_inode
     1375assert( (parent_inode != NULL) , "parent_inode is NULL\n" );
     1376assert( (child_inode_xp != XPTR_NULL ) , "child_inode is XPTR_NULL\n" );
     1377
     1378    mapper_t * mapper    = parent_inode->mapper;
     1379    xptr_t     mapper_xp = XPTR( local_cxy , mapper );
     1380
     1381// check parent mapper
     1382assert( (mapper != NULL) , "parent mapper is NULL\n");
    6321383   
    6331384    char       cname[CONFIG_VFS_MAX_NAME_LENGTH];  // name extracter from each directory entry
     
    6361387    char       lfn2[16];         // buffer for one partial cname
    6371388    char       lfn3[16];         // buffer for one partial cname
    638     page_t   * page;             // pointer on current page descriptor
    639     uint8_t  * base;             // pointer on current page base
    640     uint32_t   offset  = 0;      // byte offset in page
    641     uint32_t   index   = 0;      // page index in mapper
     1389    xptr_t     page_xp;          // extended pointer on page descriptor
     1390    xptr_t     base_xp;          // extended pointer on page base
     1391    uint8_t  * base;             // local pointer on page base
    6421392    uint32_t   attr;             // directory entry ATTR field
    6431393    uint32_t   ord;              // directory entry ORD field
    6441394    uint32_t   seq;              // sequence index
    645     uint32_t   lfn     = 0;      // LFN entries number
    646     uint32_t   size    = 0;      // searched file/dir size (bytes)
    647     uint32_t   cluster = 0;      // searched file/dir cluster index
    648     uint32_t   is_dir  = 0;      // searched file/dir type
    649     uint32_t   dentry;           // directory entry index
    650     int32_t    found   = 0;      // not found (0) / name found (1) / end of dir (-1)
     1395    uint32_t   lfn       = 0;    // LFN entries number
     1396    uint32_t   size      = 0;    // searched file/dir size (bytes)
     1397    uint32_t   cluster   = 0;    // searched file/dir cluster index
     1398    uint32_t   is_dir    = 0;    // searched file/dir type
     1399    int32_t    found     = 0;    // not found (0) / name found (1) / end of dir (-1)
     1400    uint32_t   page_id   = 0;    // page index in mapper
     1401    uint32_t   dentry_id = 0;    // directory entry index
     1402    uint32_t   offset    = 0;    // byte offset in page
    6511403
    6521404    // scan the parent directory mapper
     
    6541406    {
    6551407        // get one page
    656         page = mapper_get_page( mapper , index );
    657 
    658         assert( (page != NULL) , "bad parent mapper\n");
     1408        page_xp = mapper_remote_get_page( mapper_xp , page_id );
     1409
     1410        if( page_xp == XPTR_NULL) return EIO;
    6591411
    6601412        // get page base
    661         xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
    662         base = (uint8_t *)GET_PTR( base_xp );
    663 
    664 #if (DEBUG_FATFS_LOAD & 0x1)
    665 if( DEBUG_FATFS_LOAD < cycle )
     1413        base_xp = ppm_page2base( page_xp );
     1414        base    = (uint8_t *)GET_PTR( base_xp );
     1415
     1416#if (DEBUG_FATFS_CHILD_INIT & 0x1)
     1417if( DEBUG_FATFS_CHILD_INIT < cycle )
    6661418{
    6671419    uint32_t * buf = (uint32_t *)base;
    6681420    uint32_t line , word;
    669     printk("\n***** %s : First 16 dentries for parent inode %x\n",
    670     __FUNCTION__ , parent_inode );
     1421    printk("\n[%s] First 16 dentries for <%s>\n",
     1422    __FUNCTION__ , parent_name );
    6711423    for( line = 0 ; line < 16 ; line++ )
    6721424    {
     
    7281480                    cluster = (fatfs_get_record( DIR_FST_CLUS_HI , base + offset , 1 ) << 16) |
    7291481                              (fatfs_get_record( DIR_FST_CLUS_LO , base + offset , 1 )      ) ;
    730                     dentry  = ((index<<12) + offset)>>5;
    731                     is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
    732                     size    = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );
    733                     found   = 1;
     1482                    dentry_id = ((page_id<<12) + offset)>>5;
     1483                    is_dir    = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     1484                    size      = fatfs_get_record( DIR_FILE_SIZE , base + offset , 1 );
     1485                    found     = 1;
    7341486                }
    7351487                offset = offset + 32;
    7361488                lfn    = 0;
    7371489            }
    738         }  // end loop on directory entries
    739         index++;
     1490        }  // end loop on directory entries in page
     1491
     1492        page_id++;
    7401493        offset = 0;
     1494
    7411495    }  // end loop on pages
    7421496
     
    7461500    {
    7471501
    748 #if DEBUG_FATFS_LOAD
     1502#if DEBUG_FATFS_CHILD_INIT
    7491503cycle = (uint32_t)hal_get_cycles();
    750 if( DEBUG_FATFS_LOAD < cycle )
    751 printk("\n[DBG] %s : thread %x exit / child <%s> not found / cycle %d\n",
    752 __FUNCTION__ , CURRENT_THREAD, name, cycle );
    753 #endif
    754 
    755         return ENOENT;
    756     }
    757     else               // found searched child name
    758     {
    759         // get child inode cluster and local pointer
    760         cxy_t         child_cxy = GET_CXY( child_inode_xp );
    761         vfs_inode_t * child_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
    762 
    763         // update the child inode "type", "size", and "extend" fields
    764         vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
    765 
    766         hal_remote_s32( XPTR( child_cxy , &child_ptr->type   ) , type );
    767         hal_remote_s32( XPTR( child_cxy , &child_ptr->size   ) , size );
    768         hal_remote_s32( XPTR( child_cxy , &child_ptr->extend ) , cluster );
    769 
    770 #if DEBUG_FATFS_LOAD
     1504if( DEBUG_FATFS_CHILD_INIT < cycle )
     1505printk("\n[%s]  thread[%x,%x] exit / child <%s> not found / cycle %d\n",
     1506__FUNCTION__, this->process->pid, this->trdid, name, cycle );
     1507#endif
     1508
     1509        return -1;
     1510    }
     1511
     1512    // get child inode cluster and local pointer
     1513    cxy_t          inode_cxy = GET_CXY( child_inode_xp );
     1514    vfs_inode_t  * inode_ptr = (vfs_inode_t *)GET_PTR( child_inode_xp );
     1515
     1516    // get dentry pointers and cluster
     1517    xptr_t         dentry_xp  = hal_remote_l64( XPTR( inode_cxy , &inode_ptr->parent_xp ) ); 
     1518    vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
     1519    cxy_t          dentry_cxy = GET_CXY( dentry_xp );
     1520
     1521// dentry descriptor must be in same cluster as parent inode
     1522assert( (dentry_cxy == local_cxy) , "illegal dentry cluster\n" );
     1523
     1524    // update the child inode "type", "size", and "extend" fields
     1525    vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
     1526
     1527    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->type   ) , type );
     1528    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->size   ) , size );
     1529    hal_remote_s32( XPTR( inode_cxy , &inode_ptr->extend ) , cluster );
     1530
     1531    // update the dentry "extend" field
     1532    dentry_ptr->extend = (void *)(intptr_t)dentry_id;
     1533
     1534#if DEBUG_FATFS_CHILD_INIT
    7711535cycle = (uint32_t)hal_get_cycles();
    772 if( DEBUG_FATFS_LOAD < cycle )
    773 printk("\n[DBG] %s : thread %x exit / child <%s> loaded / cycle %d\n",
    774 __FUNCTION__ , CURRENT_THREAD, name, cycle );
    775 #endif
    776 
    777         return 0;
    778     }
    779 }  // end fatfs_inode_load()
     1536if( DEBUG_FATFS_CHILD_INIT < cycle )
     1537printk("\n[%s]  thread[%x,%x] exit / child <%s> loaded in <%s> / cycle %d\n",
     1538__FUNCTION__, this->process->pid, this->trdid, name, parent_name, cycle );
     1539#endif
     1540
     1541    return 0;
     1542
     1543}  // end fatfs_child_init()
     1544
     1545///////////////////////////////////////////////
     1546error_t fatfs_sync_inode( vfs_inode_t * inode )
     1547{
     1548
     1549// check inode pointer and cluster index
     1550assert( (inode != NULL)                  , "inode pointer undefined\n" );
     1551assert( (inode->mapper != NULL )         , "mapper pointer undefined\n" );
     1552assert( (inode->type == INODE_TYPE_FILE) , "inode must be a file\n" );     
     1553
     1554#if DEBUG_FATFS_SYNC_INODE
     1555char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     1556uint32_t   cycle = (uint32_t)hal_get_cycles();
     1557thread_t * this  = CURRENT_THREAD;
     1558vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
     1559if( DEBUG_FATFS_SYNC_INODE < cycle )
     1560printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
     1561__FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     1562#endif
     1563
     1564    error_t    error;
     1565    mapper_t * mapper;
     1566    page_t   * page;
     1567    uint32_t   page_id;
     1568
     1569    // get mapper from inode
     1570    mapper = inode->mapper;
     1571
     1572    // compute max number of pages in mapper from file size
     1573    uint32_t size  = inode->size;
     1574    uint32_t pages = size >> CONFIG_PPM_PAGE_SHIFT;
     1575    if( size & CONFIG_PPM_PAGE_MASK ) pages++;
     1576         
     1577    // get pointer on mapper radix tree
     1578    grdxt_t * rt = &mapper->rt;
     1579
     1580    // scan all pages
     1581    for( page_id = 0 ; page_id < pages ; page_id++ )
     1582    {
     1583        // get page descriptor from mapper
     1584        page = grdxt_lookup( rt , page_id );
     1585
     1586        // check all existing pages
     1587        if ( page != NULL )
     1588        {
     1589            if ( page->flags & PG_DIRTY )
     1590            {
     1591
     1592#if (DEBUG_FATFS_SYNC_INODE & 1)
     1593if( DEBUG_FATFS_SYNC_INODE < cycle )
     1594printk("\n[%s] thread[%x,%x] synchronizes page %d from <%s> mapper to IOC device\n",
     1595__FUNCTION__, page_id, name );
     1596#endif
     1597                // build extended pointer on page descriptor
     1598                xptr_t page_xp = XPTR( local_cxy , page );
     1599
     1600                // move page from mapper to device
     1601                error = fatfs_move_page( page_xp , false );
     1602
     1603                if ( error )  return -1;
     1604
     1605                // reset page dirty flag
     1606                ppm_page_undo_dirty( page_xp );
     1607            }
     1608        }
     1609    }  // end loop on pages
     1610
     1611#if DEBUG_FATFS_SYNC_INODE
     1612cycle = (uint32_t)hal_get_cycles();
     1613if( DEBUG_FATFS_SYNC_INODE < cycle )
     1614printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n",
     1615__FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     1616#endif
     1617
     1618    return 0;
     1619
     1620}  // end fatfs_sync_inode()
     1621
     1622//////////////////////////////
     1623error_t fatfs_sync_fat( void )
     1624{
     1625
     1626#if DEBUG_FATFS_SYNC_FAT
     1627uint32_t   cycle = (uint32_t)hal_get_cycles();
     1628thread_t * this  = CURRENT_THREAD;
     1629if( DEBUG_FATFS_SYNC_FAT < cycle )
     1630printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1631__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1632#endif
     1633
     1634    uint32_t   page_id;
     1635    error_t    error;
     1636
     1637    // get FAT mapper pointers an cluster
     1638    fatfs_ctx_t * fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
     1639    xptr_t        mapper_xp  = fatfs_ctx->fat_mapper_xp;
     1640    cxy_t         mapper_cxy = GET_CXY( mapper_xp );
     1641    mapper_t    * mapper_ptr = GET_PTR( mapper_xp );
     1642
     1643    // compute max number of 4 Kbytes pages in FAT mapper
     1644    // TODO : this could be improved (see fatfs.h) [AG]
     1645    uint32_t   pages = fatfs_ctx->fat_sectors_count >> 3;
     1646         
     1647    // get pointers on remote FAT mapper radix tree
     1648    grdxt_t  * rt_ptr = &mapper_ptr->rt;
     1649    xptr_t     rt_xp  = XPTR( mapper_cxy , rt_ptr );
     1650
     1651    // scan all pages
     1652    for( page_id = 0 ; page_id < pages ; page_id++ )
     1653    {
     1654        // get extended pointer on page descriptor from FAT mapper
     1655        xptr_t page_xp = grdxt_remote_lookup( rt_xp , page_id );
     1656
     1657        // check all existing pages
     1658        if ( page_xp != XPTR_NULL )
     1659        {
     1660            page_t * page_ptr = GET_PTR( page_xp );
     1661            uint32_t flags    = hal_remote_l32( XPTR( mapper_cxy , &page_ptr->flags ) );
     1662
     1663            if ( flags & PG_DIRTY )
     1664            {
     1665
     1666#if (DEBUG_FATFS_SYNC_FAT & 1)
     1667if( DEBUG_FATFS_SYNC_FAT < cycle )
     1668printk("\n[%s] thread[%x,%x] synchronizes page %d from FAT mapper to IOC device\n",
     1669__FUNCTION__, page_id );
     1670#endif
     1671                // move page from mapper to device
     1672                error = fatfs_move_page( page_xp , false );
     1673
     1674                if ( error )  return -1;
     1675
     1676                // reset page dirty flag
     1677                ppm_page_undo_dirty( page_xp );
     1678            }
     1679        }
     1680    }  // end loop on pages
     1681
     1682#if DEBUG_FATFS_SYNC_FAT
     1683cycle = (uint32_t)hal_get_cycles();
     1684if( DEBUG_FATFS_SYNC_FAT < cycle )
     1685printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1686__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1687#endif
     1688
     1689    return 0;
     1690
     1691}  // end fatfs_sync_fat()
     1692
     1693////////////////////////////////////
     1694error_t fatfs_sync_free_info( void )
     1695{
     1696
     1697#if DEBUG_FATFS_SYNC_FSINFO
     1698uint32_t   cycle = (uint32_t)hal_get_cycles();
     1699thread_t * this  = CURRENT_THREAD;
     1700if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1701printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1702__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1703#endif
     1704
     1705    uint8_t     * buffer;   // dynamically allocated aligned 512 bytes buffer
     1706    kmem_req_t    req;
     1707    error_t       error;
     1708
     1709    // get FS_INFO lba, free_ from FATFS context
     1710    fatfs_ctx_t * fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
     1711    uint32_t      lba        = fatfs_ctx->fs_info_lba;
     1712    uint32_t      hint       = fatfs_ctx->free_cluster_hint;
     1713    uint32_t      number     = fatfs_ctx->free_clusters;
     1714
     1715    // allocate buffer to store the FS_INFO sector
     1716        req.type    = KMEM_512_BYTES;
     1717    req.flags   = AF_KERNEL | AF_ZERO;
     1718        buffer      = (uint8_t *)kmem_alloc( &req );
     1719    if( buffer == NULL )
     1720    {
     1721        printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ );
     1722        return ENOMEM;
     1723    }
     1724     
     1725    // load the FS_INFO sector from device to buffer
     1726    error = dev_ioc_read( buffer , lba , 1 );
     1727    if ( error )
     1728    {
     1729        printk("\n[PANIC] in %s : cannot read FS_INFO record\n", __FUNCTION__ );
     1730        return EIO;
     1731    }
     1732
     1733    // update buffer
     1734    fatfs_set_record( FS_FREE_CLUSTERS     , buffer , 1 , number );
     1735    fatfs_set_record( FS_FREE_CLUSTER_HINT , buffer , 1 , hint );
     1736
     1737    // write modified FS_INFO sector from buffer to device
     1738    error = dev_ioc_write( buffer , lba , 1 );
     1739    if ( error )
     1740    {
     1741        printk("\n[PANIC] in %s : cannot write FS_INFO record\n", __FUNCTION__ );
     1742        return EIO;
     1743    }
     1744
     1745    // release the 512 bytes buffer
     1746    req.type = KMEM_512_BYTES;
     1747    req.ptr  = buffer;
     1748    kmem_free( &req );
     1749
     1750#if DEBUG_FATFS_SYNC_FSINFO
     1751cycle = (uint32_t)hal_get_cycles();
     1752if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1753printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1754__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1755#endif
     1756
     1757    return 0;
     1758
     1759}  // end fatfs_sync_fs_info()
     1760
     1761//////////////////////////////////////////////////////////
     1762error_t fatfs_cluster_alloc( uint32_t * searched_cluster )
     1763{
     1764    uint32_t      page_id;        // page index in mapper
     1765    uint32_t      slot_id;        // slot index in page (1024 slots per page)
     1766    uint32_t      hint;           // first free cluster index in FAT
     1767    uint32_t      free_clusters;  // total number of free clusters
     1768    vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters)
     1769    fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
     1770    fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
     1771    xptr_t        mapper_xp;      // extended pointer on FAT mapper
     1772    cxy_t         mapper_cxy;     // Fat mapper cluster identifier
     1773    xptr_t        page_xp;        // extended pointer on current page descriptor in mapper
     1774    xptr_t        slot_xp;        // extended pointer on FAT slot defined by hint
     1775    xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info
     1776    xptr_t        hint_xp;        // extended pointer on free_cluster_hint in FAT cluster
     1777    xptr_t        numb_xp;        // extended pointer on free_clusters_number in FAT cluster
     1778
     1779#if DEBUG_FATFS_CLUSTER_ALLOC
     1780uint32_t   cycle = (uint32_t)hal_get_cycles();
     1781thread_t * this  = CURRENT_THREAD;
     1782if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1783printk("\n[%s] thread[%x,%x] enter / cycle = %d\n",
     1784__FUNCTION__, this->process->pid, this->trdid, cycle );
     1785#endif
     1786
     1787    // get local pointer on VFS context (same in all clusters)
     1788    vfs_ctx = &fs_context[FS_TYPE_FATFS];
     1789
     1790    // get local pointer on local FATFS context
     1791    loc_fatfs_ctx = vfs_ctx->extend;
     1792
     1793    // get extended pointer and cluster on FAT mapper
     1794    mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
     1795    mapper_cxy = GET_CXY( mapper_xp );
     1796   
     1797    // get local pointer on FATFS context in FAT cluster
     1798    fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
     1799
     1800    // build relevant extended pointers in on free clusters info in FAT cluster
     1801    lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock );
     1802    hint_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_cluster_hint );
     1803    numb_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_clusters );
     1804
     1805    // take the lock protecting free clusters
     1806    remote_queuelock_acquire( lock_xp );
     1807
     1808    // get hint and free_clusters values from FATFS context
     1809    hint          = hal_remote_l32( hint_xp );
     1810    free_clusters = hal_remote_l32( numb_xp );
     1811       
     1812    // get page index & slot index for the first free cluster
     1813    page_id  = (hint + 1) >> 10;
     1814    slot_id  = (hint + 1) & 0x3FF;
     1815
     1816    // get relevant page from mapper
     1817    page_xp = mapper_remote_get_page( mapper_xp , page_id );
     1818
     1819    if( page_xp == XPTR_NULL )
     1820    {
     1821        printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
     1822        return -1;
     1823    }
     1824
     1825    // build extended pointer on free cluster slot
     1826    slot_xp = ppm_page2base( page_xp ) + (slot_id<<2);
     1827         
     1828#if (DEBUG_FATFS_CLUSTER_ALLOC & 1)
     1829if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1830printk("\n[%s] thread[%x,%x] get free info / hint %x / free_clusters %x\n",
     1831__FUNCTION__, this->process->pid, this->trdid, hint, free_clusters );
     1832#endif
     1833
     1834    // check "free_clusters"
     1835    if ( free_clusters == 0 )
     1836    {
     1837        printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ );
     1838        remote_queuelock_acquire( lock_xp );
     1839        return -1;
     1840    }
     1841    else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN )
     1842    {
     1843        printk("\n[WARNING] in %s : only %n free FATFS clusters\n",
     1844        __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN );
     1845    }
     1846
     1847    // check "hint"
     1848    if( hal_remote_l32( slot_xp ) != FREE_CLUSTER )
     1849    {
     1850        printk("\n[ERROR] in %s : illegal hint cluster\n", __FUNCTION__ );
     1851        remote_queuelock_acquire( lock_xp );
     1852        return -1;
     1853    }
     1854
     1855    // update allocated cluster in FAT mapper
     1856    hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX );
     1857
     1858    // update free cluster info
     1859    fatfs_free_clusters_decrement( hint + 1 );
     1860
     1861    // release free clusters busylock
     1862    remote_queuelock_release( lock_xp );
     1863
     1864#if DEBUG_FATFS_CLUSTER_ALLOC
     1865cycle = (uint32_t)hal_get_cycles();
     1866if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1867printk("\n[%s] thread[%x,%x] exit / cluster %x / cycle %d\n",
     1868__FUNCTION__, this->process->pid, this->trdid, hint + 1, cycle );
     1869#endif
     1870
     1871    *searched_cluster = hint + 1;
     1872    return 0;
     1873
     1874}  // end fat_cluster_alloc()
     1875
     1876//////////////////////////////////////////////
     1877error_t fatfs_release_inode( xptr_t inode_xp )
     1878{
     1879    vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters).
     1880    fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
     1881    fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
     1882    xptr_t        mapper_xp;      // extended pointer on FAT mapper
     1883    cxy_t         mapper_cxy;     // Fat mapper cluster identifier
     1884    xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info.
     1885    xptr_t        first_xp;       // extended pointer on inode extension
     1886    uint32_t      first_cluster;  // first cluster index for released inode
     1887    vfs_inode_t * inode_ptr;
     1888    cxy_t         inode_cxy;
     1889
     1890// check inode pointer
     1891assert( (inode_xp != XPTR_NULL) , "inode pointer is NULL\n" );
     1892
     1893    // get first_cluster from inode extension
     1894    inode_ptr     = GET_PTR( inode_xp );
     1895    inode_cxy     = GET_CXY( inode_xp );
     1896    first_xp      = XPTR( inode_cxy , &inode_ptr->extend );
     1897    first_cluster = (uint32_t)(intptr_t)hal_remote_lpt( first_xp );
     1898
     1899// check first cluster index
     1900assert( (first_cluster != 0) , "inode extend is NULL\n" );
     1901
     1902#if DEBUG_FATFS_RELEASE_INODE
     1903char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     1904uint32_t   cycle = (uint32_t)hal_get_cycles();
     1905thread_t * this  = CURRENT_THREAD;
     1906vfs_inode_get_name( inode_xp , name );
     1907if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1908printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster %x / cycle %d\n",
     1909__FUNCTION__ , this->process->pid, this->trdid, name, first_cluster, cycle );
     1910#endif
     1911
     1912    // get local pointer on VFS context (same in all clusters)
     1913    vfs_ctx = &fs_context[FS_TYPE_FATFS];
     1914
     1915    // get local pointer on local FATFS context
     1916    loc_fatfs_ctx = vfs_ctx->extend;
     1917
     1918    // get extended pointer and cluster on FAT mapper
     1919    mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
     1920    mapper_cxy = GET_CXY( mapper_xp );
     1921   
     1922    // get local pointer on FATFS context in FAT cluster
     1923    fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
     1924
     1925    // get extended pointer on free clusters lock in FAT cluster
     1926    lock_xp = XPTR( mapper_cxy , &fat_fatfs_ctx->free_lock );
     1927
     1928    // take lock protecting free clusters
     1929    remote_queuelock_acquire( lock_xp );
     1930
     1931    // call the recursive function to release all clusters from FAT mapper
     1932    if ( fatfs_recursive_release( mapper_xp , first_cluster ) )
     1933    {
     1934        printk("\n[ERROR] in %s : cannot update FAT mapper\n", __FUNCTION__ );
     1935        remote_queuelock_release( lock_xp );
     1936        return -1;
     1937    }
     1938
     1939    // release lock protecting free cluster
     1940    remote_queuelock_release( lock_xp );
     1941
     1942#if (DEBUG_FATFS_RELEASE_INODE & 1)
     1943if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1944printk("\n[%s] inode <%s> removed from FAT mapper\n", __FUNCTION__, name );
     1945#endif
     1946
     1947    // update FAT on IOC device (from FAT mapper)
     1948    if ( fatfs_sync_fat() )
     1949    {
     1950        printk("\n[ERROR] in %s : cannot update FAT on device\n", __FUNCTION__ );
     1951        return -1;
     1952    }
     1953
     1954#if (DEBUG_FATFS_RELEASE_INODE & 1)
     1955if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1956printk("\n[%s] inode <%s> removed from FAT on IOC device\n", __FUNCTION__, name );
     1957#endif
     1958
     1959    // update FS-INFO sector on IOC device (from FATFS context)
     1960    if ( fatfs_sync_free_info() )
     1961    {
     1962        printk("\n[ERROR] in %s: cannot update FS_INFO on device\n", __FUNCTION__ );
     1963        return -1;
     1964    }
     1965
     1966#if DEBUG_FATFS_RELEASE_INODE
     1967cycle = (uint32_t)hal_get_cycles();
     1968if( DEBUG_FATFS_RELEASE_INODE < cycle )
     1969printk("\n[%s] thread[%x,%x] removed <%s> inode from FATFS / cycle %d\n",
     1970__FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     1971#endif
     1972
     1973    return 0;
     1974
     1975}  // end fatfs_release_inode()
     1976
     1977/////////////////////////////////////////
     1978error_t fatfs_move_page( xptr_t  page_xp,
     1979                         bool_t  to_mapper )
     1980{
     1981    error_t       error;
     1982    vfs_inode_t * inode_ptr;
     1983    mapper_t    * mapper_ptr;     
     1984    uint32_t      page_id;     // page index in mapper
     1985
     1986#if DEBUG_FATFS_MOVE_PAGE
     1987uint32_t   cycle = (uint32_t)hal_get_cycles();
     1988thread_t * this  = CURRENT_THREAD;
     1989char       name[CONFIG_VFS_MAX_NAME_LENGTH];
     1990#endif
     1991
     1992    // get page cluster an local pointer
     1993    cxy_t    page_cxy = GET_CXY( page_xp );
     1994    page_t * page_ptr = GET_PTR( page_xp );
     1995
     1996    // get mapper pointer and page index from page descriptor
     1997    mapper_ptr = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) );
     1998    page_id    = hal_remote_l32( XPTR( page_cxy , &page_ptr->index ) );
     1999
     2000    // get pointer on local FATFS context
     2001    fatfs_ctx_t * fatfs_ctx      = fs_context[FS_TYPE_FATFS].extend;
     2002
     2003    // get page base address
     2004    xptr_t    base_xp = ppm_page2base( page_xp );
     2005    uint8_t * buffer  = (uint8_t *)GET_PTR( base_xp );
     2006 
     2007    // get inode pointer from mapper
     2008    inode_ptr  = hal_remote_lpt( XPTR( page_cxy , &mapper_ptr->inode ) );
     2009
     2010    ////////////////////////////// it is the FAT mapper
     2011    if( inode_ptr == NULL )
     2012    {
     2013        // get lba from FATFS context and page_id
     2014        uint32_t      lba        = fatfs_ctx->fat_begin_lba + (page_id << 3);
     2015 
     2016        // access device
     2017        if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 );
     2018        else            error = dev_ioc_write( buffer , lba , 8 );     
     2019
     2020        if( error ) return EIO;
     2021
     2022#if (DEBUG_FATFS_MOVE_PAGE & 0x1)
     2023if( DEBUG_FATFS_MOVE_PAGE < cycle )
     2024{
     2025    uint32_t * tab = (uint32_t *)buffer;
     2026    uint32_t line , word;
     2027    printk("\n***** %s : First 64 words of page %d in FAT mapper\n",
     2028    __FUNCTION__ , page_id );
     2029    for( line = 0 ; line < 8 ; line++ )
     2030    {
     2031        printk("%X : ", line );
     2032        for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] );
     2033        printk("\n");
     2034    }
     2035}
     2036#endif
     2037
     2038#if DEBUG_FATFS_MOVE_PAGE
     2039cycle = (uint32_t)hal_get_cycles();
     2040if( DEBUG_FATFS_MOVE_PAGE < cycle )
     2041{
     2042    if (to_mapper)
     2043         printk("\n[%s] thread[%x,%x] load page %d of FAT / cycle %d\n",
     2044         __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
     2045    else
     2046        printk("\n[%s] thread[%x,%x] sync page %d of FAT / cycle %d\n",
     2047        __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
     2048}
     2049#endif
     2050
     2051    }
     2052    ///////////////////////// it is an inode mapper
     2053    else                       
     2054    {
     2055
     2056#if DEBUG_FATFS_MOVE_PAGE
     2057vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name );
     2058#endif
     2059
     2060        uint32_t  searched_cluster;
     2061        uint32_t  first_cluster;
     2062
     2063        // get first_cluster from inode extension
     2064        void * extend = hal_remote_lpt( XPTR( page_cxy , &inode_ptr->extend ) );
     2065        first_cluster = (uint32_t)(intptr_t)extend;
     2066
     2067        // compute searched_cluster
     2068        if( page_id == 0 )            // no need to access FAT mapper
     2069        {
     2070            // searched cluster is first cluster
     2071            searched_cluster = first_cluster;
     2072        }
     2073        else                        // FAT mapper access required
     2074        {
     2075            // access FAT mapper to get searched cluster
     2076            error = fatfs_get_cluster( first_cluster,
     2077                                       page_id,
     2078                                       &searched_cluster );
     2079            if( error )  return EIO;
     2080        }
     2081
     2082        // get lba from searched_cluster
     2083        uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster );
     2084
     2085        // access device
     2086        if( to_mapper ) error = dev_ioc_sync_read ( buffer , lba , 8 );
     2087        else            error = dev_ioc_write( buffer , lba , 8 );     
     2088
     2089        if( error ) return EIO;
     2090
     2091#if (DEBUG_FATFS_MOVE_PAGE & 0x1)
     2092if( DEBUG_FATFS_MOVE_PAGE < cycle )
     2093{
     2094    uint32_t * tab = (uint32_t *)buffer;
     2095    uint32_t line , word;
     2096    printk("\n***** %s : First 64 words of page %d in <%s> mapper\n",
     2097    __FUNCTION__, page_id, name );
     2098    for( line = 0 ; line < 8 ; line++ )
     2099    {
     2100        printk("%X : ", line );
     2101        for( word = 0 ; word < 8 ; word++ ) printk("%X ", tab[(line<<3) + word] );
     2102        printk("\n");
     2103    }
     2104}
     2105#endif
     2106
     2107#if DEBUG_FATFS_MOVE_PAGE
     2108cycle = (uint32_t)hal_get_cycles();
     2109if(DEBUG_FATFS_MOVE_PAGE < cycle)
     2110{
     2111    if(to_mapper)
     2112        printk("\n[%s] thread[%x,%x] load page %d of <%s> inode / cycle %d\n",
     2113        __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle );
     2114    else
     2115        printk("\n[%s] thread[%x,%x] sync page %d of <%s> inode / cycle %d\n",
     2116        __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle );
     2117}
     2118#endif
     2119
     2120    }
     2121
     2122    return 0;
     2123
     2124}  // end fatfs_move_page()
     2125
     2126
Note: See TracChangeset for help on using the changeset viewer.