Ignore:
Timestamp:
Mar 18, 2020, 11:16:59 PM (4 years ago)
Author:
alain
Message:

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File:
1 edited

Legend:

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

    r656 r657  
    22 * fatfs.c - FATFS file system API implementation.
    33 *
    4  * Author    Alain Greiner (2016,2017,2018,2019)
     4 * Author    Alain Greiner (2016,2017,2018,2019,2020)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    122122        for( i = nbytes ; i > 0 ; i-- )
    123123        {
    124             res = (res<<8) | hal_remote_lb( buffer_xp+offset+i-1 );
     124            res = (res<<8) | hal_remote_lb( buffer_xp + offset + i-1 );
    125125        }
    126126    }
     
    129129        for( i = 0 ; i < nbytes ; i++ )
    130130        {
    131             res = (res<<8) | hal_remote_lb( buffer_xp+offset+i );
     131            res = (res<<8) | hal_remote_lb( buffer_xp + offset + i );
    132132        }
    133133    }
     
    135135
    136136}  // end fatfs_get_remote_record()
     137
     138/*
    137139
    138140//////////////////////////////////////////////////////////////////////////////////////////
     
    164166}  // end fatfs_set_record()
    165167
     168*/
     169
    166170//////////////////////////////////////////////////////////////////////////////////////////
    167171// This function writes one, two, or four bytes from a 32 bits integer to a remote
     
    185189        for( i = nbytes ; i > 0 ; i-- )
    186190        {
    187             hal_remote_sb( (buffer_xp+offset+i-1) , (uint8_t)(value>>((i-1)<<3)) );
     191            hal_remote_sb( (buffer_xp + offset + i-1 ) , (uint8_t)(value>>((i-1)<<3)) );
    188192        }
    189193    }
     
    192196        for( i = 0 ; i < nbytes ; i++ )
    193197        {
    194             hal_remote_sb( (buffer_xp+offset+i) , (uint8_t)(value>>((nbytes-1-i)<<3)) );
     198            hal_remote_sb( (buffer_xp + offset + i) , (uint8_t)(value>>((nbytes-1-i)<<3)) );
    195199        }
    196200    }
     
    470474    cxy_t         fat_cxy;         // FAT cluster identifier
    471475    fatfs_ctx_t * fatfs_ctx;       // local pointer on FATFS context in FAT cluster
    472     xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
    473476    mapper_t    * fat_mapper_ptr;  // local pointer on FAT mapper
    474477    uint32_t      page_id;         // current page index in FAT mapper
     
    482485    fatfs_ctx = GET_PTR( fatfs_ctx_xp );
    483486 
    484     // get FAT mapper pointers from FATFS context
    485     fat_mapper_xp  = hal_remote_l64( XPTR( fat_cxy , &fatfs_ctx->fat_mapper_xp ) );
    486     fat_mapper_ptr = GET_PTR( fat_mapper_xp );
    487 
    488 // check FAT cluster
    489 assert( (fat_cxy == GET_CXY( fat_mapper_xp )) , "unconsistent FAT cluster" );
     487    // get FAT mapper pointer from FATFS context
     488    fat_mapper_ptr  = hal_remote_lpt( XPTR( fat_cxy , &fatfs_ctx->fat_mapper ) );
    490489
    491490    // build extended pointer on FAT mapper radix tree
     
    575574   
    576575    // update the FS_INFO sector on IOC device
    577     return dev_ioc_move_data( IOC_SYNC_WRITE , fs_info_buffer_xp , fs_info_lba , 1 );
     576    return dev_ioc_sync_write( fs_info_buffer_xp , fs_info_lba , 1 );
    578577 
    579578}  // end fatfs_update_ioc_fsinfo()
     
    581580//////////////////////////////////////////////////////////////////////////////////////////
    582581// This static function decrements the  "free_clusters" variable, and updates the
    583 // "free_cluster_hint" variable in the FATFS context in FAT cluster, identified
    584 // by the <fat_ctx_xp> argument, when a new <cluster> has been allocated from FAT.
     582// "free_cluster_hint" variable in the FATFS context in FAT cluster,  when a new
     583// <cluster_id> has been allocated from the FAT.
     584// It synchronously updates the FS_INFO sector on the IOC device.
     585// The FATFS context in FAT cluster is identified by the <fat_ctx_xp> argument.
     586// It can be called by a thead running in any cluster.
    585587// It scan all slots in the FAT mapper seen as an array of 32 bits words, looking for the
    586 // first free slot larger than the <cluster> argument, to update "free_cluster_hint".
    587 // It synchronously updates the FS_INFO sector on the IOC device.
    588 // It can be called by a thead running in any cluster.
     588// first free slot larger than the <cluster_id>.
    589589// The lock protecting exclusive access to the FAT must be taken by the calling function.
    590590//////////////////////////////////////////////////////////////////////////////////////////
    591591// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
    592 // @ cluster       : recently allocated cluster index in FAT.
     592// @ cluster_id    : recently allocated cluster index in FAT.
    593593// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
    594594//////////////////////////////////////////////////////////////////////////////////////////
    595595static error_t fatfs_free_clusters_decrement( xptr_t    fatfs_ctx_xp,
    596                                               uint32_t  cluster )
     596                                              uint32_t  cluster_id )
    597597{
    598598    error_t       error;
    599     cxy_t         fat_cxy;        // FAT cluster identifier
    600     fatfs_ctx_t * fat_ctx_ptr;    // local pointer on fatfs context in FAT cluster
    601     xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
    602     xptr_t        hint_xp;        // extended pointer on "free_cluster_hint" shared variable
    603     xptr_t        numb_xp;        // extended pointer on "free_clusters" shared variable
    604     uint32_t      numb;           // "free_clusters" variable current value
    605     uint32_t      hint;           // "free_cluster_hint" variable current value
    606     uint32_t      page_id;        // page index in FAT mapper
    607     uint32_t      slot_id;        // slot index in one page of FAT (1024 slots per page)
    608     uint32_t      page_max;       // max number of pages in FAT mapper
    609     xptr_t        page_xp;        // extended pointer on current page in FAT mapper
    610     xptr_t        base_xp;        // extended pointer on current page base
    611     xptr_t        slot_xp;        // extended pointer on current slot in FAT mapper
     599    cxy_t         fat_cxy;         // FAT cluster identifier
     600    fatfs_ctx_t * fat_ctx_ptr;     // local pointer on fatfs context in FAT cluster
     601    mapper_t    * fat_mapper_ptr;  // local pointer on FAT mapper
     602    xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
     603    xptr_t        hint_xp;         // extended pointer on "free_cluster_hint" shared variable
     604    xptr_t        numb_xp;         // extended pointer on "free_clusters" shared variable
     605    uint32_t      page_id;         // page index in FAT mapper
     606    uint32_t      slot_id;         // slot index in one page of FAT (1024 slots per page)
     607    uint32_t      page_max;        // max number of pages in FAT mapper
     608    xptr_t        page_xp;         // extended pointer on current page in FAT mapper
     609    xptr_t        base_xp;         // extended pointer on current page base
     610    xptr_t        slot_xp;         // extended pointer on current slot in FAT mapper
     611    uint32_t      found;           // free slot found when non zero
    612612
    613613#if DEBUG_FATFS_FREE_CLUSTERS
     
    615615thread_t * this  = CURRENT_THREAD;
    616616if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
    617 printk("\n[%s] thread[%x,%x] enter for allocated cluster %x / cycle %d\n",
    618 __FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
     617printk("\n[%s] thread[%x,%x] enter for allocated cluster_id %x / cycle %d\n",
     618__FUNCTION__, this->process->pid, this->trdid, cluster_id , cycle );
    619619#endif
    620620
     
    627627    numb_xp = XPTR( fat_cxy , &fat_ctx_ptr->free_clusters );
    628628
    629     // update "free_clusters" value
    630     numb = hal_remote_l32( numb_xp ) - 1;
    631     hal_remote_s32( numb_xp , numb );
    632 
    633     // get extended pointer on FAT mapper
    634     fat_mapper_xp = hal_remote_l64( XPTR( fat_cxy , &fat_ctx_ptr->fat_mapper_xp ) );
    635 
    636     // initialise variables to scan the FAT mapper
    637     // and find the first free slot > cluster
    638     page_id  = (cluster + 1) >> 10;
    639     slot_id  = (cluster + 1) & 0x3FF;
     629    // get pointers on FAT mapper from FATFS context
     630    fat_mapper_ptr = hal_remote_lpt( XPTR( fat_cxy , &fat_ctx_ptr->fat_mapper ) );
     631    fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
     632
     633    // initialise the loop variables to scan the FAT mapper
     634    page_id  = (cluster_id + 1) >> 10;
     635    slot_id  = (cluster_id + 1) & 0x3FF;
    640636    page_max = hal_remote_l32( XPTR( fat_cxy, &fat_ctx_ptr->fat_sectors_count ) ) >> 3;
    641 
    642     // scan FAT mapper / loop on pages
    643     while ( page_id < page_max )           
     637    found    = 0;
     638
     639    // scan FAT mapper : first loop on pages
     640    while ( (page_id < page_max) && (found == 0) )           
    644641    {
    645642        // get current page from mapper
    646         page_xp = mapper_remote_get_page( fat_mapper_xp , page_id );
     643        page_xp = mapper_get_fat_page( fat_mapper_xp , page_id );
    647644
    648645        if( page_xp == XPTR_NULL )
     
    655652        base_xp = ppm_page2base( page_xp );
    656653
    657         // scan FAT mapper / loop on slots
    658         while ( slot_id < 1024 )
     654        // scan the FAT mapper : second loop on slots
     655        while ( (slot_id < 1024) && (found == 0) )
    659656        {
    660657            // get extended pointer on current slot
     
    664661            if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER )
    665662            {
    666                 // update "free_cluster_hint" value
    667                 hint = (page_id << 10) + slot_id - 1;
    668                 hal_remote_s32( hint_xp , hint );
    669 
    670                 // update FS_INFO sector on IOC device
    671                 error = fatfs_update_ioc_fat( fatfs_ctx_xp,
    672                                               page_id,
    673                                               page_id );
    674 
    675                 if( error )
    676                 {
    677                     printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
    678                     return -1;
    679                 }
     663                // exit both loops
     664                found = 1;
     665            }
     666            else
     667            {
     668                // update slot_id if not found
     669                slot_id++;
     670            }
     671        }  // end loop on slots
     672
     673        // update page_id & slot_id variables if not found
     674        if( found == 0 )
     675        {
     676            page_id++;
     677            slot_id = 0;
     678        }
     679    }  // end loop on pages
     680
     681    if( found )  // free cluster found
     682    {
     683        // update "free_clusters" and "free_cluster_hint" value in FATFS context
     684        hal_remote_atomic_add( numb_xp , -1 );
     685        hal_remote_s32( hint_xp , (page_id << 10) + slot_id - 1 );
     686
     687        // update FS_INFO sector on IOC device
     688        error = fatfs_update_ioc_fsinfo( fatfs_ctx_xp );
     689
     690        if( error )
     691        {
     692            printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
     693            return -1;
     694        }
    680695
    681696#if DEBUG_FATFS_FREE_CLUSTERS
    682 cycle = (uint32_t)hal_get_cycles();
    683 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
    684 printk("\n[%s] thread[%x,%x] exit / hint %x / free %x / cycle %d\n",
     697if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
     698printk("\n[%s] thread[%x,%x] exit / hint %x / free %x\n",
    685699__FUNCTION__, this->process->pid, this->trdid,
    686 hal_remote_l32(hint_xp), hal_remote_l32(numb_xp), cycle );
    687 #endif
    688                 return 0;
    689             }
    690 
    691             // update slot_id
    692             slot_id = 0;
    693 
    694         }  // end loop on slots
    695 
    696         // update page_id & slot_id variables
    697         page_id++;
    698         slot_id = 0;
    699 
    700     }  // end loop on pages
    701 
    702     // return error if no free cluster found
    703     printk("\n[ERROR] in %s : No free cluster found\n", __FUNCTION__ );
    704     return -1;
     700hal_remote_l32(hint_xp), hal_remote_l32(numb_xp) );
     701#endif
     702        return 0;
     703    }
     704    else  // free cluster not found
     705    {
     706        printk("\n[ERROR] in %s : No free cluster_id found\n", __FUNCTION__ );
     707        return -1;
     708    }
    705709   
    706710}  // end fatfs_free_clusters_decrement()
     
    709713// This static function increments the "free_clusters" variable, and updates the
    710714// "free_cluster_hint" variables in the FATFS context in FAT cluster, identified
    711 // by the <fat_ctx_xp> argument, when a FATFS cluster is released.
     715// by the <fat_ctx_xp> argument, when a FATFS <cluster_id> has been released.
    712716// If the released cluster index is smaller than the current (hint) value,
    713717// it set "free_cluster_hint" <= cluster.
    714 // It does NOT update the  FS_INFO sector on the IOC device.
     718// It does NOT update the  FS_INFO sector on the IOC device, as this is done by the
     719// calling fatfs_release_inode() function.
    715720// It can be called by a thead running in any cluster.
    716721// The lock protecting exclusive access to the FAT must be taken by the calling function.
    717722//////////////////////////////////////////////////////////////////////////////////////////
    718723// @ fatfs_ctx_xp  : extended pointer on FATFS context in FAT cluster.
    719 // @ cluster       : recently released cluster index in FAT.
     724// @ cluster_id    : recently released cluster index in FAT.
    720725// @ return 0 if success, return -1 if the FS_INFO sector cannot be updated.
    721726//////////////////////////////////////////////////////////////////////////////////////////
    722727static error_t fatfs_free_clusters_increment( xptr_t   fatfs_ctx_xp,
    723                                               uint32_t cluster )
    724 {
    725     error_t       error;
     728                                              uint32_t cluster_id )
     729{
    726730    cxy_t         fat_cxy;      // FAT cluster identifier
    727731    fatfs_ctx_t * fat_ctx_ptr;  // local pointer on fatfs context in FAT cluster
     
    735739thread_t * this  = CURRENT_THREAD;
    736740if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
    737 printk("\n[%s] thread[%x,%x] enter for released cluster %x / cycle %d\n",
    738 __FUNCTION__, this->process->pid, this->trdid, cluster , cycle );
     741printk("\n[%s] thread[%x,%x] enter for released cluster_id %x / cycle %d\n",
     742__FUNCTION__, this->process->pid, this->trdid, cluster_id , cycle );
    739743#endif
    740744
     
    753757    // update "numb" and "hint" variables as required
    754758    numb++;
    755     if ( (cluster - 1) < hint ) hint = cluster - 1;
     759    if ( (cluster_id - 1) < hint ) hint = cluster_id - 1;
    756760
    757761    // update free_clusters
     
    759763    hal_remote_s32( hint_xp , hint );
    760764
    761     // update FS_INFO sector on IOC device
    762     error = fatfs_update_ioc_fsinfo( fatfs_ctx_xp );
    763 
    764     if( error )
    765     {
    766         printk("\n[ERROR] in %s : cannot update FS_INFO on IOC\n", __FUNCTION__ );
    767         return -1;
    768     }
    769 
    770765#if DEBUG_FATFS_FREE_CLUSTERS
    771 cycle = (uint32_t)hal_get_cycles();
    772 if( DEBUG_FATFS_FREE_CLUSTERS < (uint32_t)hal_get_cycles() )
    773 printk("\n[%s] thread[%x,%x] exit / hint %x / free %x / cycle %d\n",
     766if( DEBUG_FATFS_FREE_CLUSTERS < cycle )
     767printk("\n[%s] thread[%x,%x] exit / hint %x / free %x\n",
    774768__FUNCTION__, this->process->pid, this->trdid,
    775 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ), cycle );
     769hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) );
    776770#endif
    777771
     
    853847
    854848//////////////////////////////////////////////////////////////////////////////////////////
     849// This static function access the FAT mapper to allocate a new cluster in the FATFS,
     850// and returns in <searched_cluster_id> the FATFS cluster index of a free cluster.
     851// It updates the FAT mapper (handling miss from IOC device if required) :
     852// - if the <last_cluster_id> is zero, the new cluster is the first allocated cluster,
     853//   and the <searched_cluster_id> FAT slot is set to END_OF_CHAIN_CLUSTER.
     854// - if the <last_cluster_id> argument is not zero, the new cluster is not the first,
     855//   the <last_cluster_id> FAT slot is set to <searched_cluster_id>,
     856//   the <searched_cluster_id> FAT slot is set to END_OF_CHAIN_CLUSTER.
     857// This function also updates the  two "free_cluster_hint" and "free_clusters" variables
     858// stored in the FATFS context. It takes the rwlock stored in the FATFS context in the
     859// FAT cluster to get exclusive access to the FAT.
     860// This function synchronously updates the FAT region on IOC device.
     861// It can be called by a thread running in any cluster as it uses remote accesses.
     862//////////////////////////////////////////////////////////////////////////////////////////
     863// @ last_cluster_id      : [in]  previous last cluster index.
     864// @ searched_cluster_id  : [out] allocated cluster index.
     865// @ return 0 if success / return -1 if no more free clusters on IOC device.
     866//////////////////////////////////////////////////////////////////////////////////////////
     867static error_t fatfs_cluster_alloc( uint32_t   last_cluster_id,
     868                                    uint32_t * searched_cluster_id )
     869{
     870    error_t       error;
     871    uint32_t      free_clusters;   // total number of free clusters
     872    uint32_t      hint;            // hint + 1 is the first free cluster
     873    uint32_t      new_cluster_id;  // allocated cluster index in FAT
     874    uint32_t      new_page_id;     // allocated cluster page index in FAT mapper
     875    uint32_t      new_slot_id;     // allocated cluster slot index in page (1024 slots per page)
     876    xptr_t        new_page_xp;     // extended pointer on FAT page for allocated cluster
     877    xptr_t        new_slot_xp;     // extended pointer on allocated cluster slot in FAT
     878    uint32_t      last_page_id;    // last cluster page index in FAT mapper
     879    uint32_t      last_slot_id;    // last cluster slot index in page (1024 slots per page)
     880    xptr_t        last_slot_xp;    // extended pointer on last cluster slot in FAT
     881    xptr_t        last_page_xp;    // extended pointer on FAT page for last cluster
     882    vfs_ctx_t   * vfs_ctx;         // local pointer on VFS context (same in all clusters)
     883    fatfs_ctx_t * loc_fatfs_ctx;   // local pointer on local FATFS context
     884    fatfs_ctx_t * fat_fatfs_ctx;   // local pointer on FATFS context in FAT cluster
     885    mapper_t    * fat_mapper_ptr;  // local pointer on FAT mapper
     886    xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
     887    cxy_t         fat_cxy;         // FAT mapper cluster identifier
     888    xptr_t        lock_xp;         // extended pointer on lock protecting free clusters info
     889    xptr_t        hint_xp;         // extended pointer on free_cluster_hint in FAT cluster
     890    xptr_t        free_xp;         // extended pointer on free_clusters_number in FAT cluster
     891   
     892#if DEBUG_FATFS_CLUSTER_ALLOC
     893uint32_t   cycle = (uint32_t)hal_get_cycles();
     894thread_t * this  = CURRENT_THREAD;
     895if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     896printk("\n[%s] thread[%x,%x] enter / lats_cluster_id %x / cycle = %d\n",
     897__FUNCTION__, this->process->pid, this->trdid, last_cluster_id, cycle );
     898#endif
     899
     900    // get local pointer on VFS context (same in all clusters)
     901    vfs_ctx = &fs_context[FS_TYPE_FATFS];
     902
     903    // get local pointer on local FATFS context
     904    loc_fatfs_ctx = vfs_ctx->extend;
     905
     906    // get FAT cluster
     907    fat_cxy = CONFIG_VFS_ROOT_CXY;
     908
     909    // get pointers on FAT mapper
     910    fat_mapper_ptr = loc_fatfs_ctx->fat_mapper;
     911    fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
     912
     913    // get local pointer on FATFS context in FAT cluster
     914    fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
     915
     916    // build relevant extended pointers on free clusters info in FAT cluster
     917    lock_xp = XPTR( fat_cxy , &fat_fatfs_ctx->lock );
     918    hint_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint );
     919    free_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters );
     920
     921    // take the FAT lock in write mode
     922    remote_rwlock_wr_acquire( lock_xp );
     923
     924    // get hint and free_clusters values from FATFS context in FAT cluster
     925    hint          = hal_remote_l32( hint_xp );
     926    free_clusters = hal_remote_l32( free_xp );
     927       
     928#if (DEBUG_FATFS_CLUSTER_ALLOC & 1)
     929if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     930printk("\n[%s] thread[%x,%x] get free info : hint %x / free_clusters %x\n",
     931__FUNCTION__, this->process->pid, this->trdid, hint, free_clusters );
     932#endif
     933
     934    // check "free_clusters"
     935    if ( free_clusters == 0 )
     936    {
     937        printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ );
     938        remote_rwlock_wr_release( lock_xp );
     939        return -1;
     940    }
     941    else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN )
     942    {
     943        printk("\n[WARNING] in %s : only %d free FATFS clusters\n",
     944        __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN );
     945    }
     946
     947    // get new cluster, page & slot indexes in FAT
     948    new_cluster_id = hint + 1;
     949    new_page_id    = new_cluster_id >> 10;
     950    new_slot_id    = new_cluster_id & 0x3FF;
     951
     952    // get relevant FAT page descriptor from FAT mapper
     953    new_page_xp = mapper_get_fat_page( fat_mapper_xp , new_page_id );
     954
     955    if( new_page_xp == XPTR_NULL )
     956    {
     957        printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
     958        remote_rwlock_wr_release( lock_xp );
     959        return -1;
     960    }
     961
     962    // build extended pointer on new cluster slot in FAT mapper
     963    new_slot_xp = ppm_page2base( new_page_xp ) + (new_slot_id << 2);
     964         
     965    // check selected cluster actually free
     966    if( hal_remote_l32( new_slot_xp ) != FREE_CLUSTER )
     967    {
     968        printk("\n[ERROR] in %s : selected cluster_id %x not free\n",
     969        __FUNCTION__, new_cluster_id );
     970        remote_rwlock_wr_release( lock_xp );
     971        return -1;
     972    }
     973
     974    // update new_cluster slot in FAT mapper
     975    hal_remote_s32( new_slot_xp  , END_OF_CHAIN_CLUSTER_MIN );
     976
     977    // handle last_cluster_id argument if non zero
     978    if( last_cluster_id )
     979    {
     980        // get last cluster page & slot indexes in FAT
     981        last_page_id    = last_cluster_id >> 10;
     982        last_slot_id    = last_cluster_id & 0x3FF;
     983
     984        // get relevant FAT page descriptor from FAT mapper
     985        last_page_xp = mapper_get_fat_page( fat_mapper_xp , last_page_id );
     986
     987        if( last_page_xp == XPTR_NULL )
     988        {
     989            printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
     990            remote_rwlock_wr_release( lock_xp );
     991            return -1;
     992        }
     993
     994        // build extended pointer on new cluster slot in FAT mapper
     995        last_slot_xp = ppm_page2base( last_page_xp ) + (last_slot_id << 2);
     996         
     997        // check last cluster actually end of chain
     998        if( hal_remote_l32( last_slot_xp ) != END_OF_CHAIN_CLUSTER_MIN )
     999        {
     1000            printk("\n[ERROR] in %s : last_cluster_id %x not END_OF_CHAIN\n",
     1001            __FUNCTION__, last_cluster_id );
     1002            remote_rwlock_wr_release( lock_xp );
     1003            return -1;
     1004        }
     1005
     1006        // update last_cluster slot in FAT mapper
     1007        hal_remote_s32( last_slot_xp , new_cluster_id );
     1008    }
     1009    else
     1010    {
     1011        last_page_xp = XPTR_NULL;
     1012    }
     1013
     1014    // update the FAT new_page on device
     1015    error = fatfs_move_page( new_page_xp , IOC_SYNC_WRITE );
     1016
     1017    if( error )
     1018    {
     1019        printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
     1020        remote_rwlock_wr_release( lock_xp );
     1021        return -1;
     1022    }
     1023
     1024    // update the FAT last_page on device when required
     1025    if( (last_page_xp != XPTR_NULL) && (last_page_xp != new_page_xp) )
     1026    {
     1027        error = fatfs_move_page( last_page_xp , IOC_SYNC_WRITE );
     1028
     1029        if( error )
     1030        {
     1031            printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
     1032            remote_rwlock_wr_release( lock_xp );
     1033            return -1;
     1034        }
     1035    }
     1036
     1037    // update free cluster info in FATFS context and in FS_INFO sector
     1038    error = fatfs_free_clusters_decrement( XPTR( fat_cxy , fat_fatfs_ctx ) , new_cluster_id );
     1039
     1040    if( error )
     1041    {
     1042        printk("\n[ERROR] in %s : cannot update free cluster info\n", __FUNCTION__ );
     1043        remote_rwlock_wr_release( lock_xp );
     1044        return -1;
     1045    }
     1046
     1047    // release FAT lock
     1048    remote_rwlock_wr_release( lock_xp );
     1049
     1050#if DEBUG_FATFS_CLUSTER_ALLOC
     1051cycle = (uint32_t)hal_get_cycles();
     1052if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
     1053printk("\n[%s] thread[%x,%x] exit / allocated cluster_id %x in FAT / cycle %d\n",
     1054__FUNCTION__, this->process->pid, this->trdid, new_cluster_id, cycle );
     1055#endif
     1056
     1057    *searched_cluster_id = new_cluster_id;
     1058    return 0;
     1059
     1060}  // end fatfs_cluster_alloc()
     1061
     1062
     1063//////////////////////////////////////////////////////////////////////////////////////////
    8551064// This static function access the FAT (File Allocation Table), stored in the FAT mapper,
    8561065// and returns in <searched_cluster_id> the FATFS cluster_id for a given page of a given
    857 // inode, identified by the <searched_page_id> argument, that is the page index in file
     1066// inode, identified by the <searched_page_id> argument that is the page index in file
    8581067// (i.e. the page index in file mapper). The entry point in the FAT is defined by the
    8591068// <first_cluster_id> argument, that is the cluster_id of an already allocated cluster.
     
    8611070// fatfs_inode extension), or any page of the file whose <first_page_id> argument
    8621071// is smaller than the searched <first_page_id> argument.
    863 // This function can be called by a thread running in any cluster, as it uses remote
    864 // access primitives when the FAT mapper is remote.
     1072// This function can be called by a thread running in any cluster.
    8651073// The FAT mapper being a WRITE-THROUGH cache, this function updates the FAT mapper
    8661074// from informations stored on IOC device in case of miss when scanning the FAT mapper.
     
    8851093    uint32_t   current_cluster_id;     // index of cluster in FATFS
    8861094    xptr_t     lock_xp;                // extended pointer on FAT lock
     1095    xptr_t     fat_mapper_xp;          // extended pointer on FAT mapper
     1096    mapper_t * fat_mapper_ptr;         // local pointer on FAT mapper
     1097    cxy_t      fat_cxy;                // FAT cluster
     1098    error_t    error;
    8871099
    8881100assert( (searched_page_id > first_page_id) ,
     
    8931105thread_t * this  = CURRENT_THREAD;
    8941106if( DEBUG_FATFS_GET_CLUSTER < cycle )
    895 printk("\n[%s] thread[%x,%x] enter / first_cluster_id %x / searched_page_id %d / cycle %d\n",
    896 __FUNCTION__, this->process->pid, this->trdid, first_cluster_id, searched_page_id, cycle );
     1107printk("\n[%s] thread[%x,%x] enter / frst_pid %x / frst_cid %x / srch_pid %d / cycle %d\n",
     1108__FUNCTION__, this->process->pid, this->trdid,
     1109first_page_id, first_cluster_id, searched_page_id, cycle );
    8971110#endif
    8981111
     
    9031116    fatfs_ctx_t * loc_fatfs_ctx = vfs_ctx->extend;
    9041117
    905     // get extended pointer and cluster on FAT mapper
    906     xptr_t fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    907     cxy_t  fat_cxy        = GET_CXY( fat_mapper_xp );
     1118    // get FAT cluster
     1119    fat_cxy = CONFIG_VFS_ROOT_CXY;
     1120   
     1121    // get pointers on FAT mapper
     1122    fat_mapper_ptr = loc_fatfs_ctx->fat_mapper;
     1123    fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
    9081124
    9091125    // get local pointer on FATFS context in FAT cluster
     
    9311147
    9321148        // get pointer on current page descriptor in FAT mapper
    933         xptr_t current_page_xp = mapper_remote_get_page( fat_mapper_xp , fat_page_index );
     1149        xptr_t current_page_xp = mapper_get_fat_page( fat_mapper_xp , fat_page_index );
    9341150
    9351151        if( current_page_xp == XPTR_NULL )
     
    9421158
    9431159        // get pointer on buffer containing the FAT mapper page
    944         xptr_t base_xp = ppm_page2base( current_page_xp );
    945         uint32_t * buffer = (uint32_t *)GET_PTR( base_xp );
     1160        xptr_t     base_xp = ppm_page2base( current_page_xp );
     1161        uint32_t * buffer  = (uint32_t *)GET_PTR( base_xp );
    9461162
    9471163        // get next_cluster_id from FAT slot 
    9481164        uint32_t next_cluster_id = hal_remote_l32( XPTR( fat_cxy, &buffer[fat_slot_index] ) );
    9491165
    950         // allocate a new FAT cluster when there is no cluster
    951         // allocated on device for the current page
     1166        // allocate a new FAT cluster when END_OF_CHAIN found
    9521167        if( next_cluster_id >= END_OF_CHAIN_CLUSTER_MIN )
    9531168        {
     
    9561171
    9571172            // allocate a new cluster_id (and update both FAT mapper and FAT on device).
    958             error_t error = fatfs_cluster_alloc( &next_cluster_id );
    959 
     1173            error = fatfs_cluster_alloc( current_cluster_id,
     1174                                         &next_cluster_id );
    9601175            if( error )
    9611176            {
     
    9681183#if (DEBUG_FATFS_GET_CLUSTER & 1)
    9691184if( DEBUG_FATFS_GET_CLUSTER < cycle )
    970 printk("\n[%s] allocated a new cluster_id %d in FATFS\n",
     1185printk("\n[%s] allocated a new cluster_id %x in FATFS\n",
    9711186__FUNCTION__, next_cluster_id );
    9721187#endif
     
    9771192#if (DEBUG_FATFS_GET_CLUSTER & 1)
    9781193if( DEBUG_FATFS_GET_CLUSTER < cycle )
    979 printk("\n[%s] traverse FAT / fat_page_index %d / fat_slot_index %d / next_cluster_id %x\n",
    980 __FUNCTION__, fat_page_index, fat_slot_index , next_cluster_id );
     1194printk("\n[%s] traverse FAT / current_cluster_id %x / next_cluster_id %x\n",
     1195__FUNCTION__, current_cluster_id , next_cluster_id );
    9811196#endif
    9821197
     
    9911206#if DEBUG_FATFS_GET_CLUSTER
    9921207if( DEBUG_FATFS_GET_CLUSTER < cycle )
    993 printk("\n[%s] thread[%x,%x] exit / searched_cluster_id = %d\n",
    994 __FUNCTION__, this->process->pid, this->trdid, current_cluster_id );
     1208printk("\n[%s] thread[%x,%x] exit / frst_pid %d / frst_cid %x / srch_pid %d / srch_cid %x\n",
     1209__FUNCTION__, this->process->pid, this->trdid,
     1210first_page_id, first_cluster_id, searched_page_id, current_cluster_id );
    9951211#endif
    9961212
     
    10001216}  // end fatfs_get_cluster()
    10011217
    1002 
    1003 
    1004 
    1005 
    1006 //////////////////////////////////////////////////////////////////////////////////////////
    1007 //              FATFS specific extern functions
    1008 //////////////////////////////////////////////////////////////////////////////////////////
    1009 
    1010 ///////////////////////////////////
    1011 void fatfs_display_ctx( cxy_t cxy )
    1012 {
    1013     // get pointer on local FATFS context
    1014     vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
    1015         fatfs_ctx_t * ctx     = hal_remote_lpt( XPTR( cxy , &vfs_ctx->extend ) );
    1016 
    1017     uint32_t fat_sectors       = hal_remote_l32( XPTR( cxy , &ctx->fat_sectors_count ) );
    1018     uint32_t sector_size       = hal_remote_l32( XPTR( cxy , &ctx->bytes_per_sector ) );
    1019     uint32_t sec_per_clus      = hal_remote_l32( XPTR( cxy , &ctx->sectors_per_cluster ) );
    1020     uint32_t fat_lba           = hal_remote_l32( XPTR( cxy , &ctx->fat_begin_lba ) );
    1021     uint32_t data_lba          = hal_remote_l32( XPTR( cxy , &ctx->cluster_begin_lba ) );
    1022     uint32_t fsinfo_lba        = hal_remote_l32( XPTR( cxy , &ctx->fs_info_lba ) );
    1023     uint32_t root_dir_clus     = hal_remote_l32( XPTR( cxy , &ctx->root_dir_cluster ) );
    1024     uint32_t free_clusters     = hal_remote_l32( XPTR( cxy , &ctx->free_clusters ) );
    1025     uint32_t free_cluster_hint = hal_remote_l32( XPTR( cxy , &ctx->free_cluster_hint ) );
    1026     xptr_t   mapper_xp         = hal_remote_l64( XPTR( cxy , &ctx->fat_mapper_xp ) );
    1027     void   * fs_info_buffer    = hal_remote_lpt( XPTR( cxy , &ctx->fs_info_buffer ) );
    1028 
    1029     printk("\n*** FAT context in cluster %x\n"
    1030            "- fat_sectors       = %d\n"
    1031            "- sector size       = %d\n"
    1032            "- cluster size      = %d\n"
    1033            "- fat_lba           = %x\n"
    1034            "- data_lba          = %x\n"
    1035            "- fsinfo_lba        = %x\n"
    1036            "- root_dir_cluster  = %x\n"
    1037            "- free_clusters     = %x\n"
    1038            "- free_cluster_hint = %x\n"
    1039            "- fat_mapper_ptr    = %x\n"
    1040            "- fs_info_buffer    = %x\n",
    1041            cxy,
    1042            fat_sectors,
    1043            sector_size,
    1044            sector_size * sec_per_clus,
    1045            fat_lba,
    1046            data_lba,
    1047            fsinfo_lba,
    1048            root_dir_clus,
    1049            free_clusters,
    1050            free_cluster_hint,
    1051            GET_PTR( mapper_xp ),
    1052            fs_info_buffer );
    1053 
    1054 }  // end fatfs_ctx_display()
    1055 
    1056 //////////////////////////////////////////
    1057 void fatfs_display_fat( uint32_t  page_id,
    1058                         uint32_t  min_slot,
    1059                         uint32_t  nb_slots )
    1060 {
    1061     uint32_t line;
    1062 
    1063     // compute number of lines to display
    1064     uint32_t min_line = min_slot >> 3;
    1065     uint32_t max_line = (min_slot + nb_slots - 1) >> 3;
    1066 
    1067     // get pointer on local FATFS context
    1068     vfs_ctx_t   * vfs_ctx       = &fs_context[FS_TYPE_FATFS];
    1069     fatfs_ctx_t * loc_fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
    1070 
    1071     // get pointers on FAT mapper (in FAT cluster)
    1072     xptr_t     mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    1073     cxy_t      mapper_cxy = GET_CXY( mapper_xp );
    1074 
    1075     // get pointer on FATFS context in FAT cluster
    1076     fatfs_ctx_t * fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );
    1077  
    1078     // get current value of hint and free_clusters
    1079     uint32_t hint = hal_remote_l32( XPTR( mapper_cxy , &fat_fatfs_ctx->free_cluster_hint ) );
    1080     uint32_t free = hal_remote_l32( XPTR( mapper_cxy , &fat_fatfs_ctx->free_clusters ) );
    1081 
    1082     // get extended pointer on requested page descriptor in FAT mapper
    1083     xptr_t page_xp = mapper_remote_get_page( mapper_xp , page_id );
    1084 
    1085     // get pointers on requested page base
    1086     xptr_t     base_xp  = ppm_page2base( page_xp );
    1087     void     * base     = GET_PTR( base_xp );
    1088 
    1089     printk("\n***** FAT mapper / cxy %x / page_id %d / base %x / free_clusters %x / hint %x\n",
    1090     mapper_cxy, page_id, base, free, hint );
    1091 
    1092     for( line = min_line ; line <= max_line ; line++ )
    1093     {
    1094         printk("%d : %X | %X | %X | %X | %X | %X | %X | %X\n", (line<<3),
    1095         hal_remote_l32( base_xp + ((line<<5)      ) ),
    1096         hal_remote_l32( base_xp + ((line<<5) + 4  ) ),
    1097         hal_remote_l32( base_xp + ((line<<5) + 8  ) ),
    1098         hal_remote_l32( base_xp + ((line<<5) + 12 ) ),
    1099         hal_remote_l32( base_xp + ((line<<5) + 16 ) ),
    1100         hal_remote_l32( base_xp + ((line<<5) + 20 ) ),
    1101         hal_remote_l32( base_xp + ((line<<5) + 24 ) ),
    1102         hal_remote_l32( base_xp + ((line<<5) + 28 ) ) );
    1103     }
    1104 
    1105 }  // end fatfs_display_fat()
    1106 
    1107 
    1108 
    1109 ///////////////////////////////////////////////////////////////////////////////////////
    1110 // Generic API : the following functions are called by the kernel VFS
    1111 //               and must be defined by all supported file systems.
    1112 ///////////////////////////////////////////////////////////////////////////////////////
    1113 
    1114 /////////////////////////////////////
    1115 fatfs_ctx_t * fatfs_ctx_alloc( void )
    1116 {
    1117     kmem_req_t    req;
    1118         req.type    = KMEM_KCM;
    1119         req.order   = bits_log2( sizeof(fatfs_ctx_t) );
    1120     req.flags   = AF_KERNEL | AF_ZERO;
    1121 
    1122         return kmem_alloc( &req );
    1123 }
    1124 
    1125 //////////////////////////////////////////////
    1126 void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx )
    1127 {
    1128     error_t       error;
    1129     kmem_req_t    req;
    1130     uint8_t     * buffer;
    1131     xptr_t        buffer_xp;
    1132 
    1133 #if DEBUG_FATFS_CTX_INIT
    1134 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1135 thread_t * this  = CURRENT_THREAD;
    1136 if( DEBUG_FATFS_CTX_INIT < cycle )
    1137 printk("\n[%s] thread[%x,%x] enter for fatfs_ctx = %x / cycle %d\n",
    1138 __FUNCTION__ , this->process->pid, this->trdid, fatfs_ctx , cycle );
    1139 #endif
    1140 
    1141 // check argument
    1142 assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL" );
    1143 
    1144 // check only cluster 0 does FATFS initialization
    1145 assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS");
    1146 
    1147     // allocate a permanent 512 bytes buffer to store
    1148     // - temporarily the BOOT sector
    1149     // - permanently the FS_INFO sector
    1150         req.type    = KMEM_KCM;
    1151     req.order   = 9;                    // 512 bytes
    1152     req.flags   = AF_KERNEL | AF_ZERO;
    1153         buffer      = kmem_alloc( &req );
    1154 
    1155     if( buffer == NULL )
    1156     {
    1157         printk("\n[PANIC] in %s : cannot allocate buffer\n", __FUNCTION__ );
    1158         hal_core_sleep();
    1159     }
    1160      
    1161     buffer_xp   = XPTR( local_cxy , buffer );
    1162 
    1163     // load the BOOT record from device
    1164     error = dev_ioc_move_data( IOC_SYNC_READ , buffer_xp , 0 , 1 );
    1165 
    1166     if ( error )
    1167     {
    1168         printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ );
    1169         hal_core_sleep();
    1170     }
    1171 
    1172 #if (DEBUG_FATFS_CTX_INIT & 0x1)
    1173 if( DEBUG_FATFS_CTX_INIT < cycle )
    1174 putb( "boot record", buffer , 256 );
    1175 #endif
    1176 
    1177     // get sector size from boot record
    1178     uint32_t sector_size = fatfs_get_record( BPB_BYTSPERSEC , buffer );
    1179     if ( sector_size != 512 )
    1180     {
    1181         printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ );
    1182         hal_core_sleep();
    1183     }
    1184 
    1185     // get cluster size from boot record
    1186     uint32_t nb_sectors = fatfs_get_record( BPB_SECPERCLUS , buffer );
    1187     if ( nb_sectors != 8 )
    1188     {
    1189         printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ );
    1190         hal_core_sleep();
    1191     }
    1192 
    1193     // get number of FAT copies from boot record
    1194     uint32_t nb_fats = fatfs_get_record( BPB_NUMFATS , buffer );
    1195     if ( nb_fats != 1 )
    1196     {
    1197         printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ );
    1198         hal_core_sleep();
    1199     }
    1200 
    1201     // get number of sectors in FAT from boot record
    1202     uint32_t fat_sectors = fatfs_get_record( BPB_FAT32_FATSZ32 , buffer );
    1203     if ( (fat_sectors & 0xF) != 0 )
    1204     {
    1205         printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ );
    1206         hal_core_sleep();
    1207     }
    1208 
    1209     // get root cluster from boot record
    1210     uint32_t root_cluster = fatfs_get_record( BPB_FAT32_ROOTCLUS , buffer );
    1211     if ( root_cluster != 2 )
    1212     {
    1213         printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ );
    1214         hal_core_sleep();
    1215     }
    1216 
    1217     // get FAT lba from boot record
    1218     uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer );
    1219 
    1220     // get FS_INFO sector lba from boot record
    1221     uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer );
    1222 
    1223     // load the FS_INFO record from device
    1224     error = dev_ioc_move_data( IOC_SYNC_READ , buffer_xp , fs_info_lba , 1 );
    1225 
    1226     if ( error )
    1227     {
    1228         printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ );
    1229         hal_core_sleep();
    1230     }
    1231 
    1232     // get free_clusters number from FS_INFO record
    1233     uint32_t free_clusters = fatfs_get_record( FS_FREE_CLUSTERS , buffer );
    1234     if ( free_clusters >= fat_sectors << 7 )
    1235     {
    1236         printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ );
    1237         hal_core_sleep();
    1238     }
    1239 
    1240     // get free_cluster_hint from FS_INFO record
    1241     uint32_t free_cluster_hint = fatfs_get_record( FS_FREE_CLUSTER_HINT , buffer );
    1242 
    1243     if ( free_cluster_hint >= fat_sectors << 7 )
    1244     {
    1245         printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ );
    1246         hal_core_sleep();
    1247     }
    1248 
    1249     // allocate a mapper for the FAT itself
    1250     mapper_t * fat_mapper = mapper_create( FS_TYPE_FATFS );
    1251     if ( fat_mapper == NULL )
    1252     {
    1253         printk("\n[PANIC] in %s : no memory for FAT mapper\n", __FUNCTION__ );
    1254         hal_core_sleep();
    1255     }
    1256 
    1257     // the inode field is NULL for the FAT mapper
    1258     fat_mapper->inode = NULL;
    1259 
    1260     // initialize the FATFS context
    1261     fatfs_ctx->fat_begin_lba         = fat_lba;
    1262     fatfs_ctx->fat_sectors_count     = fat_sectors;
    1263     fatfs_ctx->bytes_per_sector      = sector_size;
    1264     fatfs_ctx->sectors_per_cluster   = nb_sectors;
    1265     fatfs_ctx->cluster_begin_lba     = fat_lba + fat_sectors;
    1266     fatfs_ctx->root_dir_cluster      = 2;
    1267     fatfs_ctx->fat_mapper_xp         = XPTR( local_cxy , fat_mapper );
    1268     fatfs_ctx->fs_info_lba           = fs_info_lba;
    1269     fatfs_ctx->free_clusters         = free_clusters;
    1270     fatfs_ctx->free_cluster_hint     = free_cluster_hint;
    1271     fatfs_ctx->fs_info_buffer        = buffer;
    1272 
    1273     remote_rwlock_init( XPTR( local_cxy , &fatfs_ctx->lock ) , LOCK_FATFS_FAT );
    1274 
    1275 #if (DEBUG_FATFS_CTX_INIT & 0x1)
    1276 if( DEBUG_FATFS_CTX_INIT < cycle )
    1277 fatfs_ctx_display( fatfs_ctx );
    1278 #endif
    1279 
    1280 #if DEBUG_FATFS_CTX_INIT
    1281 cycle = (uint32_t)hal_get_cycles();
    1282 if( DEBUG_FATFS_CTX_INIT < cycle )
    1283 printk("\n[%s]  thread[%x,%x] exit for fatfs_ctx = %x / cycle %d\n",
    1284 __FUNCTION__, this->process->pid, this->trdid, fatfs_ctx, cycle );
    1285 #endif
    1286 
    1287 }  // end fatfs_ctx_init()
    1288 
    1289 /////////////////////////////////////////////////
    1290 void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx )
    1291 {
    1292     kmem_req_t    req;
    1293     req.type = KMEM_KCM;
    1294     req.ptr  = fatfs_ctx;
    1295     kmem_free( &req );
    1296 }
    1297 
    1298 ///////////////////////////////////////////////
    1299 error_t fatfs_add_dentry( vfs_inode_t  * inode,
    1300                           vfs_dentry_t * dentry )
    1301 {
    1302     error_t       error;
    1303     uint32_t      length;        // dentry name length
    1304     uint32_t      nb_lfn;        // number or required LFN
    1305     char          sfn[11];       // buffer for SFN name
    1306     uint8_t       checksum;      // name checksum
    1307     mapper_t    * mapper;        // loal pointer on parent inode mapper
    1308     xptr_t        mapper_xp;     // extended pointer on parent inode mapper
    1309     xptr_t        child_xp;      // extended pointer on child inode
    1310     cxy_t         child_cxy;     // child inode cluster
    1311     vfs_inode_t * child_ptr;     // child inode local pointer
    1312     uint32_t      size;          // child inode size
    1313     uint32_t      type;          // child inode type
    1314     uint32_t      cluster;       // child inode cluster index
    1315 
    1316 #if DEBUG_FATFS_ADD_DENTRY
    1317 char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1318 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1319 thread_t * this  = CURRENT_THREAD;
    1320 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    1321 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1322 printk("\n[%s]  thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
    1323 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1324 #endif
    1325 
    1326 // check arguments
    1327 assert( (inode != NULL) , "inode pointer is NULL\n" );
    1328 assert( (dentry != NULL) , "dentry pointer is NULL\n" );
    1329 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
    1330  
    1331     // get pointers on directory mapper
    1332     mapper    = inode->mapper;
    1333     mapper_xp = XPTR( local_cxy , mapper );
    1334 
    1335     // get extended pointers on remote child inode
    1336     child_xp  = dentry->child_xp;
    1337     child_cxy = GET_CXY( child_xp );
    1338     child_ptr = GET_PTR( child_xp );
    1339 
    1340     // get relevant infos from child inode
    1341     type    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) );
    1342     size    =                     hal_remote_l32( XPTR( child_cxy , &child_ptr->size ) );
    1343     cluster = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( child_cxy , &child_ptr->extend ) );
    1344 
    1345     // analyse dentry name
    1346     error = fatfs_name_format( dentry->name,
    1347                                &length,
    1348                                &nb_lfn,
    1349                                sfn,
    1350                                &checksum );
    1351     if ( error )
    1352     {
    1353         printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ );
    1354         return -1;
    1355     }
    1356                                
    1357     // Search end of directory with two embedded loops:
    1358     // - scan the pages in the mapper
    1359     // - scan the entries in each page to find NO_MORE_ENTRY
    1360 
    1361     xptr_t     page_xp;                 // extended pointer on page descriptor
    1362     xptr_t     base_xp;                 // extended pointer on page base
    1363     uint8_t  * base;                    // local pointer on page base (array of bytes)
    1364     uint32_t   page_id = 0;             // page index in mapper
    1365     uint32_t   offset  = 0;             // position in page
    1366     uint32_t   found   = 0;             // NO_MORE_ENTRY found
    1367 
    1368     // loop on pages in mapper
    1369     while ( found == 0 )
    1370     {
    1371         // get extended pointer on page descriptor in mapper
    1372         page_xp  = mapper_remote_get_page( mapper_xp , page_id );
    1373 
    1374         if ( page_xp == XPTR_NULL )
    1375         {
    1376             printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
    1377             return -1;
    1378         }
    1379        
    1380         // get pointer on page base
    1381         base_xp = ppm_page2base( page_xp );
    1382         base = GET_PTR( base_xp );
    1383 
    1384         // loop on directory entries in this page
    1385         while ( (offset < 4096) && (found == 0) )
    1386         {
    1387             if ( fatfs_get_record( LDIR_ORD, (base + offset) ) == NO_MORE_ENTRY )
    1388             {
    1389                 found = 1;
    1390             } 
    1391             else
    1392             {
    1393                 offset = offset + 32;
    1394             }
    1395         }  // end loop on entries
    1396 
    1397         if ( found == 0 )
    1398         {
    1399             page_id++;
    1400             offset = 0;
    1401         }
    1402     }  // end loop on pages
    1403 
    1404     // Modify the directory mapper: depending on the name length,
    1405     // the new child requires to write (3, 4, or 5) directory entries.
    1406     // To actually register the new child, we use a 5 steps FSM
    1407     // (one state per entry to be written), that is traversed as:
    1408     // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE
    1409     // At most two pages are modified:
    1410     // - the page containing the NO_MORE_ENTRY is always modified
    1411     // - the following page can be modified if the name spread on to pages.
    1412 
    1413     char * name = dentry->name;
    1414 
    1415     uint32_t step;          // FSM state
    1416 
    1417     if      ( nb_lfn == 1 ) step = 3;
    1418     else if ( nb_lfn == 2 ) step = 4;
    1419     else if ( nb_lfn == 3 ) step = 5;
    1420    
    1421     uint8_t  * entry;       // pointer on directory entry to be written
    1422     uint32_t   i;           // byte index in one 32 bytes directory
    1423     uint32_t   c;           // character index in name
    1424 
    1425     while ( step )   
    1426     {
    1427         // when the new child is split on two pages,
    1428         // we need to access a new page in mapper
    1429         if ( offset >= 4096 )
    1430         {
    1431             // copy the modified page to IOC device
    1432             fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1433 
    1434             // get the next page in FAT mapper
    1435             page_xp  = mapper_remote_get_page( mapper_xp , page_id + 1 );
    1436 
    1437             if ( page_xp == XPTR_NULL )
    1438             {
    1439                 printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
    1440                 return -1;
    1441             }
    1442        
    1443             // get pointer on page base
    1444             base_xp = ppm_page2base( page_xp );
    1445             base = GET_PTR( base_xp );
    1446            
    1447             // update offset
    1448             offset = 0;
    1449         }
    1450 
    1451         // compute directory entry address
    1452         entry = base + offset;
    1453 
    1454 #if (DEBUG_FATFS_ADD_DENTRY & 1)
    1455 cycle = (uint32_t)hal_get_cycles();
    1456 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1457 printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d / cycle %d\n",
    1458 __FUNCTION__, step, offset, nb_lfn, cycle );
    1459 #endif
    1460 
    1461         // write 32 bytes (one directory entry) per iteration
    1462         switch ( step )
    1463         {
    1464             case 5:   // write LFN3 entry
    1465             {
    1466                 c = 26;
    1467                 // scan the 32 bytes in dir_entry
    1468                 for ( i = 0 ; i < 32 ; i++ )
    1469                 {
    1470                     if (i == 0)
    1471                     {
    1472                         if ( nb_lfn == 3) entry[i] = 0x43;
    1473                         else              entry[i] = 0x03;
    1474                     }
    1475                     else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
    1476                                 ((i >= 14) && (i<=25) && ((i&1)==0))   ||
    1477                                 ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
    1478                               ( c < length ) )
    1479                     {
    1480                                           entry[i] = name[c];
    1481                                           c++;
    1482                     }
    1483                     else if (i == 11)     entry[i] = 0x0F;
    1484                     else if (i == 13)     entry[i] = checksum;
    1485                     else                  entry[i] = 0x00;
    1486                 }
    1487                 step--;
    1488                 break;
    1489             }
    1490             case 4:   // write LFN2 entry 
    1491             {
    1492                 c = 13;
    1493                 // scan the 32 bytes in dir_entry
    1494                 for ( i = 0 ; i < 32 ; i++ )
    1495                 {
    1496                     if (i == 0)
    1497                     {
    1498                         if ( nb_lfn == 2) entry[i] = 0x42;
    1499                         else              entry[i] = 0x02;
    1500                     }
    1501                     else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
    1502                                 ((i >= 14) && (i<=25) && ((i&1)==0))   ||
    1503                                 ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
    1504                               ( c < length ) )
    1505                     {
    1506                                           entry[i] = name[c];
    1507                                           c++;
    1508                     }
    1509                     else if (i == 11)     entry[i] = 0x0F;
    1510                     else if (i == 13)     entry[i] = checksum;
    1511                     else                  entry[i] = 0x00;
    1512                 }
    1513                 step--;
    1514                 break;
    1515             }
    1516             case 3:   // Write LFN1 entry   
    1517             {
    1518                 c = 0;
    1519                 // scan the 32 bytes in dir_entry
    1520                 for ( i = 0 ; i < 32 ; i++ )
    1521                 {
    1522                     if (i == 0)
    1523                     {
    1524                         if ( nb_lfn == 1) entry[i] = 0x41;
    1525                         else              entry[i] = 0x01;
    1526                     }
    1527                     else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
    1528                                 ((i >= 14) && (i<=25) && ((i&1)==0))   ||
    1529                                 ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
    1530                               ( c < length ) )
    1531                     {
    1532                                           entry[i] = name[c];
    1533                                           c++;
    1534                     }
    1535                     else if (i == 11)     entry[i] = 0x0F;
    1536                     else if (i == 13)     entry[i] = checksum;
    1537                     else                  entry[i] = 0x00;
    1538                 }
    1539                 step--;
    1540                 break;
    1541             }
    1542             case 2:   // write NORMAL entry     
    1543             {
    1544                 // scan the 32 bytes in dir_entry
    1545                 for ( i = 0 ; i < 32 ; i++ )
    1546                 {
    1547                     if      ( i < 11 )                              // 8.3 SFN
    1548                     {
    1549                                           entry[i] = sfn[i];
    1550                     }
    1551                     else if (i == 11)                               // ATTR
    1552                     {
    1553                         if (type == INODE_TYPE_DIR)  entry[i] = 0x10;
    1554                         else                         entry[i] = 0x20;
    1555                     }
    1556                     else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2
    1557                     else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3
    1558                     else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0
    1559                     else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1
    1560                     else if (i == 28)     entry[i] = size>>0;       // size.B0
    1561                     else if (i == 29)     entry[i] = size>>8;       // size.B1
    1562                     else if (i == 30)     entry[i] = size>>16;      // size.B2
    1563                     else if (i == 31)     entry[i] = size>>24;      // size.B3
    1564                     else                  entry[i] = 0x00;
    1565                 }
    1566 
    1567                 // update the "extend" field in dentry descriptor
    1568                 dentry->extend = (void*)(intptr_t)(((page_id<<12) + offset)>>5);
    1569 
    1570                 step--;
    1571                 break;
    1572             }
    1573             case 1:   // write NOMORE entry 
    1574             {
    1575                 entry [0] = 0x00;
    1576                 step--;
    1577                 break;
    1578             }
    1579         } // end switch step
    1580 
    1581         offset += 32;
    1582 
    1583     } // exit while     
    1584 
    1585 #if (DEBUG_FATFS_ADD_DENTRY & 1)
    1586 cycle = (uint32_t)hal_get_cycles();
    1587 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1588 printk("\n[%s]  thread[%x,%x] before IOC access / cycle %d\n",
    1589 __FUNCTION__, this->process->pid, this->trdid, cycle );
    1590 #endif
    1591 
    1592     // copy the modified page to the IOC device
    1593     fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1594 
    1595 #if DEBUG_FATFS_ADD_DENTRY
    1596 cycle = (uint32_t)hal_get_cycles();
    1597 if( DEBUG_FATFS_ADD_DENTRY < cycle )
    1598 printk("\n[%s]  thread[%x,%x] exit / parent <%s> / child <%s> / cycle %d\n",
    1599 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1600 #endif
    1601 
    1602     return 0;
    1603 
    1604 }  // end fatfs_add_dentry()
    1605 
    1606 //////////////////////////////////////////////////
    1607 error_t fatfs_remove_dentry( vfs_inode_t  * inode,
    1608                              vfs_dentry_t * dentry )
    1609 {
    1610     xptr_t     mapper_xp;  // extended pointer on mapper
    1611     mapper_t * mapper;     // local pointer on mapper
    1612     xptr_t     page_xp;    // extended pointer on mapper page descriptor
    1613     xptr_t     base_xp;    // extended pointer on mapper page base
    1614     uint8_t  * base;       // local pointer on mapper page base
    1615 
    1616 #if DEBUG_FATFS_REMOVE_DENTRY
    1617 char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1618 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1619 thread_t * this  = CURRENT_THREAD;
    1620 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    1621 if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1622 printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n",
    1623 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1624 #endif
    1625 
    1626 // check arguments
    1627 assert( (inode != NULL) , "inode pointer is NULL\n" );
    1628 assert( (dentry != NULL) , "dentry pointer is NULL\n" );
    1629 assert( (inode->type == INODE_TYPE_DIR) , "inode is not a directory\n" );
    1630 assert( (inode->mapper != NULL ) , "mapper pointer is NULL\n" );
    1631 
    1632     // get pointers on directory mapper
    1633     mapper    = inode->mapper;
    1634     mapper_xp = XPTR( local_cxy , mapper );
    1635 
    1636     // compute number of LFN entries
    1637     uint32_t nb_lfn;
    1638     uint32_t name_length = strlen( dentry->name );
    1639 
    1640     if      ( name_length <= 13 ) nb_lfn  = 1;
    1641     else if ( name_length <= 26 ) nb_lfn  = 2;
    1642     else                          nb_lfn  = 3;
    1643 
    1644     // we must invalidate (2, 3 or 4) 32 bytes entries:
    1645     // the NORMAL entry (registered in dentry->extend) and all preceding LFN entries
    1646     // At most two pages are modified:
    1647     // - the page containing the NORMAL entry is always modified.
    1648     // - the preceding page is modified when the name spread on two pages.
    1649 
    1650     // get 32 bytes directory entry index from dentry->extend
    1651     uint32_t  dentry_id  = (uint32_t)(intptr_t)dentry->extend;
    1652 
    1653     // get page index and offset in parent directory mapper
    1654     uint32_t  page_id    = dentry_id >> 7;
    1655     uint32_t  offset     = (dentry_id & 0x7F)<<5;
    1656 
    1657 #if DEBUG_FATFS_REMOVE_DENTRY & 1
    1658 if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1659 printk("\n[%s] dentry_id %x / page_id %x / offset %x\n",
    1660 __FUNCTION__, dentry_id, page_id, offset );
    1661 #endif
    1662 
    1663     // get extended pointer on page descriptor from parent directory mapper
    1664     page_xp  = mapper_remote_get_page( mapper_xp , page_id );
    1665 
    1666     if ( page_xp == XPTR_NULL )
    1667     {
    1668         printk("\n[ERROR] in %s : cannot extend directory mapper\n", __FUNCTION__ );
    1669         return -1;
    1670     }
    1671        
    1672     // get pointers on page base
    1673     base_xp = ppm_page2base( page_xp );
    1674     base    = GET_PTR( base_xp );
    1675 
    1676     // invalidate NORMAL entry in directory cache
    1677     base[offset] = 0xE5;
    1678 
    1679     // invalidate LFN entries
    1680     while ( nb_lfn )
    1681     {
    1682         if (offset == 0)  // we must load page (page_id - 1)
    1683         {
    1684 
    1685 // check page_id
    1686 assert( (page_id > 0), "page_id and offset cannot be both 0\n" );
    1687 
    1688             // copy the modified page to the IOC device
    1689             fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1690 
    1691             // get extended pointer on page descriptor from parent directory mapper
    1692             page_xp  = mapper_remote_get_page( mapper_xp , page_id );
    1693 
    1694             if ( page_xp == XPTR_NULL )
    1695             {
    1696                 printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
    1697                 return -1;
    1698             }
    1699        
    1700             // get pointers on page base
    1701             base_xp = ppm_page2base( page_xp );
    1702             base    = GET_PTR( base_xp );
    1703 
    1704             // update offset
    1705             offset = 4096;
    1706         }
    1707 
    1708         offset = offset - 32;
    1709 
    1710 // check for LFN entry
    1711 assert( (fatfs_get_record( DIR_ATTR, base + offset ) == ATTR_LONG_NAME_MASK ),
    1712 "this directory entry must be a LFN\n");
    1713 
    1714         // invalidate LFN entry
    1715         base[offset] = 0xE5;
    1716 
    1717         nb_lfn--;
    1718     }     
    1719 
    1720     // copy the modified page to the IOC device
    1721     fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
    1722    
    1723 
    1724 #if DEBUG_FATFS_REMOVE_DENTRY
    1725 cycle = (uint32_t)hal_get_cycles();
    1726 if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
    1727 printk("\n[%s] thread[%x,%x] exit / parent %s / child %s / cycle %d\n",
    1728 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
    1729 #endif
    1730 
    1731     return 0;
    1732 
    1733 }  // end fatfs_remove_dentry
    1734 
    1735 
    17361218//////////////////////////////////////////////////////////////////////////////////////////////
    1737 // This static function scan the pages of a mapper containing a FAT32 directory, identified
    1738 // by the <mapper> argument, to find the directory entry identified by the <name> argument,
    1739 // and return a pointer on the directory entry, described as and array of 32 bytes, and the
    1740 // index of this entry in the FAT32 mapper, seen as an array of 32 bytes entries.
    1741 // It is called by the fatfs_new_dentry() and fatfs_update_dentry() functions.
    1742 // It must be called by a thread running in the cluster containing the mapper.
     1219// This static function scan the pages of a directory mapper, identified by the <mapper_xp>
     1220// argument, to find the directory entry identified by the <name> argument, and returns
     1221// a pointer on the directory entry, described as an array of 32 bytes, and the index of
     1222// this entry in the FAT32 mapper, seen as an array of 32 bytes entries.
     1223// It makes a local copy of each directory entry to reduce the number of remote accesses.
     1224// It is called by the fatfs_new_dentry_from_mapper() function.
     1225// It can be called by a thread running in any cluster.
    17431226//////////////////////////////////////////////////////////////////////////////////////////////
    1744 // @ mapper    : [in]  local pointer on directory mapper.
     1227// @ mapper_xp : [in]  extended pointer on directory mapper.
    17451228// @ name      : [in]  searched directory entry name.
    17461229// @ entry     : [out] buffer for the pointer on the 32 bytes directory entry (when found).
     
    17481231// @ return 0 if found / return 1 if not found / return -1 if mapper access error.
    17491232//////////////////////////////////////////////////////////////////////////////////////////////
    1750 static error_t fatfs_scan_directory( mapper_t *  mapper,
     1233static error_t fatfs_scan_directory( xptr_t      mapper_xp,
    17511234                                     char     *  name,
    17521235                                     uint8_t  ** entry,
    17531236                                     uint32_t *  index )
    17541237{
    1755     // Two embedded loops to scan the directory mapper:
    1756     // - scan the parent directory mapper pages
    1757     // - scan the directory entries in each 4 Kbytes page
    1758 
    1759 // check parent_inode and child_inode
    1760 assert( (mapper != NULL) , "mapper pointer is NULL\n" );
    1761 assert( (name   != NULL ), "child name is undefined\n" );
    1762 assert( (entry  != NULL ), "entry buffer undefined\n" );
     1238    uint8_t  buf[32];   // local buffer for one FAT32 directory entry
     1239
     1240// check arguments
     1241assert( (mapper_xp != XPTR_NULL) , "mapper pointer is NULL\n" );
     1242assert( (name      != NULL     ) , "child name is undefined\n" );
    17631243
    17641244#if DEBUG_FATFS_SCAN_DIRECTORY
    1765 char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1766 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1767 thread_t * this  = CURRENT_THREAD;
    1768 vfs_inode_get_name( XPTR( local_cxy , mapper->inode ) , parent_name );
     1245char          parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1246uint32_t      cycle      = (uint32_t)hal_get_cycles();
     1247thread_t    * this       = CURRENT_THREAD;
     1248mapper_t    * mapper_ptr = GET_PTR( mapper_xp );
     1249cxy_t         mapper_cxy = GET_CXY( mapper_xp );
     1250vfs_inode_t * inode_ptr  = hal_remote_lpt( XPTR( mapper_cxy , &mapper_ptr->inode ) );
     1251vfs_inode_get_name( XPTR( mapper_cxy , inode_ptr ) , parent_name );
    17691252if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    17701253printk("\n[%s]  thread[%x,%x] enter to search child <%s> in parent <%s> / cycle %d\n",
     
    17771260    char       lfn2[16];         // buffer for one partial cname
    17781261    char       lfn3[16];         // buffer for one partial cname
    1779     xptr_t     mapper_xp;        // extended pointer on mapper descriptor
    1780     xptr_t     page_xp;          // extended pointer on page descriptor
    1781     xptr_t     base_xp;          // extended pointer on page base
    1782     uint8_t  * base;             // local pointer on page base
     1262    xptr_t     page_xp;          // extended pointer on one page descriptor
     1263    xptr_t     base_xp;          // extended pointer on one page base
    17831264    uint8_t    attr;             // directory entry ATTR field
    17841265    uint8_t    ord;              // directory entry ORD field
     
    17891270    uint32_t   offset    = 0;    // byte offset in page
    17901271
    1791     mapper_xp = XPTR( local_cxy , mapper );
     1272    // Two embedded loops to scan the directory mapper:
     1273    // - scan the parent directory mapper pages
     1274    // - scan the directory entries in each 4 Kbytes page
    17921275
    17931276    // scan the mapper pages
     
    17951278    {
    17961279        // get one page
    1797         page_xp = mapper_remote_get_page( mapper_xp , page_id );
     1280        page_xp = mapper_get_page( mapper_xp , page_id );
    17981281
    17991282        if( page_xp == XPTR_NULL)
     
    18041287        // get page base
    18051288        base_xp = ppm_page2base( page_xp );
    1806         base    = (uint8_t *)GET_PTR( base_xp );
    1807 
    1808 #if (DEBUG_FATFS_SCAN_DIRECTORY & 0x1)
     1289
     1290#if (DEBUG_FATFS_SCAN_DIRECTORY & 1)
    18091291if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    18101292mapper_display_page( mapper_xp , page_xp , 256 );
     
    18131295        while( (offset < 4096) && (found == 0) )
    18141296        {
    1815             attr = fatfs_get_record( DIR_ATTR , base + offset );   
    1816             ord  = fatfs_get_record( LDIR_ORD , base + offset );   
     1297            // makes a local copy of current directory entry  (32 bytes)
     1298            hal_remote_memcpy( XPTR( local_cxy , buf ) , base_xp + offset , 32 );
     1299
     1300            // get attr and ord from local buffer
     1301            attr = fatfs_get_record( DIR_ATTR , buf );   
     1302            ord  = fatfs_get_record( LDIR_ORD , buf );   
    18171303
    18181304            if (ord == NO_MORE_ENTRY)                 // no more entry => break
     
    18321318                seq = ord & 0x3;
    18331319                lfn = (seq > lfn) ? seq : lfn;   
    1834                 if      ( seq == 1 ) fatfs_get_name_from_long( base + offset, lfn1 );
    1835                 else if ( seq == 2 ) fatfs_get_name_from_long( base + offset, lfn2 );
    1836                 else if ( seq == 3 ) fatfs_get_name_from_long( base + offset, lfn3 );
     1320                if      ( seq == 1 ) fatfs_get_name_from_long( buf , lfn1 );
     1321                else if ( seq == 2 ) fatfs_get_name_from_long( buf , lfn2 );
     1322                else if ( seq == 3 ) fatfs_get_name_from_long( buf , lfn3 );
    18371323                offset = offset + 32;
    18381324            }
     
    18421328                if      ( lfn == 0 )
    18431329                {
    1844                     fatfs_get_name_from_short( base + offset , cname );
     1330                    fatfs_get_name_from_short( buf , cname );
    18451331                }
    18461332                else if ( lfn == 1 )
     
    18631349                if ( strcmp( name , cname ) == 0 )
    18641350                {
     1351                    uint8_t * base = GET_PTR( base_xp );
    18651352                    *entry = base + offset;
    1866                     *index = ((page_id<<12) + offset)>>5;
    1867                     found     = 1;
     1353                    *index = ( (page_id << 12) + offset ) >> 5;
     1354                    found  = 1;
    18681355                }
    18691356                offset = offset + 32;
    18701357                lfn    = 0;
    18711358            }
     1359
    18721360        }  // end loop on directory entries in page
    18731361
     
    18811369
    18821370#if DEBUG_FATFS_SCAN_DIRECTORY
    1883 cycle = (uint32_t)hal_get_cycles();
    18841371if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    18851372printk("\n[%s]  thread[%x,%x] exit / found child <%s> in <%s>\n",
     
    18921379
    18931380#if DEBUG_FATFS_SCAN_DIRECTORY
    1894 cycle = (uint32_t)hal_get_cycles();
    18951381if( DEBUG_FATFS_SCAN_DIRECTORY < cycle )
    18961382printk("\n[%s]  thread[%x,%x] exit / child <%s> in <%s> not found\n",
     
    19091395
    19101396
    1911 
    1912 /////////////////////////////////////////////////////
    1913 error_t fatfs_new_dentry( vfs_inode_t * parent_inode,
    1914                           char        * name,
    1915                           xptr_t        child_inode_xp )
    1916 {
    1917     uint8_t      * entry;            // pointer on FAT32 directory entry (array of 32 bytes)
    1918     uint32_t       index;            // index of FAT32 directory entry in mapper
    1919     mapper_t     * mapper;           // pointer on directory mapper
    1920     uint32_t       cluster;          // directory entry cluster
    1921     uint32_t       size;             // directory entry size
    1922     bool_t         is_dir;           // directory entry type (file/dir)
    1923     xptr_t         root_xp;          // extended pointer on root of parent dentries
    1924     xptr_t         iter_xp;          // iterator for this list
    1925     cxy_t          child_inode_cxy;  // child inode cluster 
    1926     vfs_inode_t  * child_inode_ptr;  // child inode local pointer
    1927     xptr_t         dentry_xp;        // extended pointer on searched dentry descriptor
    1928     cxy_t          dentry_cxy;       // cluster identifier of dentry (must be local_cxy)
    1929     vfs_dentry_t * dentry_ptr;       // local pointer
    1930     error_t        error;
    1931 
    1932     char           parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
    1933 
    1934 // check arguments
    1935 assert( (parent_inode   != NULL)       , "parent_inode is NULL\n" );
    1936 assert( (name           != NULL)       , "name is NULL\n" );
    1937 assert( (child_inode_xp != XPTR_NULL ) , "child_inode is NULL\n" );
    1938 
    1939     // get child inode cluster and local pointer
    1940     child_inode_cxy = GET_CXY( child_inode_xp );
    1941     child_inode_ptr = GET_PTR( child_inode_xp );
    1942 
    1943     // build extended pointer on root of list of parent dentries
    1944     root_xp = XPTR( child_inode_cxy , &child_inode_ptr->parents );
    1945 
    1946 // check child inode has at least one parent
    1947 assert( (xlist_is_empty( root_xp ) == false ), "child inode must have one parent\n");
    1948 
    1949 #if DEBUG_FATFS_NEW_DENTRY
     1397//////////////////////////////////////////////////////////////////////////////////////////
     1398//              FATFS debug functions
     1399//////////////////////////////////////////////////////////////////////////////////////////
     1400
     1401///////////////////////////////////
     1402void fatfs_display_ctx( cxy_t cxy )
     1403{
     1404    // get pointer on local FATFS context
     1405    vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
     1406        fatfs_ctx_t * ctx     = hal_remote_lpt( XPTR( cxy , &vfs_ctx->extend ) );
     1407
     1408    uint32_t fat_sectors       = hal_remote_l32( XPTR( cxy , &ctx->fat_sectors_count ) );
     1409    uint32_t sector_size       = hal_remote_l32( XPTR( cxy , &ctx->bytes_per_sector ) );
     1410    uint32_t sec_per_clus      = hal_remote_l32( XPTR( cxy , &ctx->sectors_per_cluster ) );
     1411    uint32_t fat_lba           = hal_remote_l32( XPTR( cxy , &ctx->fat_begin_lba ) );
     1412    uint32_t data_lba          = hal_remote_l32( XPTR( cxy , &ctx->cluster_begin_lba ) );
     1413    uint32_t fsinfo_lba        = hal_remote_l32( XPTR( cxy , &ctx->fs_info_lba ) );
     1414    uint32_t root_dir_clus     = hal_remote_l32( XPTR( cxy , &ctx->root_dir_cluster ) );
     1415    uint32_t free_clusters     = hal_remote_l32( XPTR( cxy , &ctx->free_clusters ) );
     1416    uint32_t free_cluster_hint = hal_remote_l32( XPTR( cxy , &ctx->free_cluster_hint ) );
     1417    void   * fat_mapper        = hal_remote_lpt( XPTR( cxy , &ctx->fat_mapper ) );
     1418    void   * fs_info_buffer    = hal_remote_lpt( XPTR( cxy , &ctx->fs_info_buffer ) );
     1419
     1420    printk("\n*** FAT context in cluster %x\n"
     1421           "- fat_sectors       = %d\n"
     1422           "- sector size       = %d\n"
     1423           "- cluster size      = %d\n"
     1424           "- fat_lba           = %x\n"
     1425           "- data_lba          = %x\n"
     1426           "- fsinfo_lba        = %x\n"
     1427           "- root_dir_cluster  = %x\n"
     1428           "- free_clusters     = %x\n"
     1429           "- free_cluster_hint = %x\n"
     1430           "- fat_mapper        = %x\n"
     1431           "- fs_info_buffer    = %x\n",
     1432           cxy,
     1433           fat_sectors,
     1434           sector_size,
     1435           sector_size * sec_per_clus,
     1436           fat_lba,
     1437           data_lba,
     1438           fsinfo_lba,
     1439           root_dir_clus,
     1440           free_clusters,
     1441           free_cluster_hint,
     1442           fat_mapper,
     1443           fs_info_buffer );
     1444
     1445}  // end fatfs_display_ctx()
     1446
     1447//////////////////////////////////////////
     1448void fatfs_display_fat( uint32_t  min_slot,
     1449                        uint32_t  nb_slots )
     1450{
     1451    // one FAT mapper page contains 1024 slots = 128 lines of 8 slots
     1452
     1453    uint32_t   page_id;
     1454    uint32_t   line;
     1455    cxy_t      fat_cxy;         // FAT cluster
     1456    mapper_t * mapper;          // local pointer on FAT mapper
     1457    xptr_t     mapper_xp;       // extended pointer on fat_mapper
     1458    uint32_t   min_cluster_id;  // index of min slot to be displayed
     1459    uint32_t   min_page_id;     // index of min page to be displayed
     1460    uint32_t   min_line_id;     // index of min line in min page ( < 128 )
     1461    uint32_t   max_cluster_id;  // index of max slot to be displayed
     1462    uint32_t   max_page_id;     // index of max page to be displayed
     1463    uint32_t   max_line_id;     // index of max line in max page ( < 128 )
     1464
     1465    // compute min values
     1466    min_cluster_id = min_slot & 0xFFFFFFF8;
     1467    min_line_id    = (min_cluster_id & 0x3FF) >> 3;
     1468    min_page_id    = min_cluster_id >> 10;
     1469
     1470    // compute max values
     1471    max_cluster_id = min_slot + nb_slots - 1;
     1472    max_line_id    = (max_cluster_id & 0x3FF) >> 3;
     1473    max_page_id    = max_cluster_id >> 10;
     1474
     1475    // get pointer on local FATFS context
     1476    vfs_ctx_t   * vfs_ctx       = &fs_context[FS_TYPE_FATFS];
     1477    fatfs_ctx_t * loc_fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
     1478
     1479    // get FAT cluster
     1480    fat_cxy = CONFIG_VFS_ROOT_CXY;
     1481
     1482    // get pointers on FAT mapper (in FAT cluster)
     1483    mapper    = loc_fatfs_ctx->fat_mapper;
     1484    mapper_xp = XPTR( fat_cxy , mapper );
     1485
     1486    // get pointer on FATFS context in FAT cluster
     1487    fatfs_ctx_t * fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
     1488 
     1489    // get current value of hint and free_clusters
     1490    uint32_t hint = hal_remote_l32( XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint ) );
     1491    uint32_t free = hal_remote_l32( XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters ) );
     1492
     1493    printk("\n***** FAT mapper / cxy %x / free_clusters %x / hint %x\n", fat_cxy, free, hint );
     1494
     1495    // scan all pages as required by min_page_id and max_page_id
     1496    for( page_id = min_page_id ; page_id <= max_page_id ; page_id++ )
     1497    {
     1498        // get extended pointer on requested page descriptor in FAT mapper
     1499        xptr_t page_xp = mapper_get_fat_page( mapper_xp , page_id );
     1500
     1501        // get extended pointer on requested page base
     1502        xptr_t     base_xp  = ppm_page2base( page_xp );
     1503
     1504        // compute min_line & max_line in current page
     1505        uint32_t min_line = (page_id == min_page_id) ? min_line_id : 0;
     1506        uint32_t max_line = (page_id == max_page_id) ? max_line_id : 127;
     1507
     1508        // loop on lines in current page
     1509        for( line = min_line ; line <= max_line ; line++ )
     1510        {
     1511            printk("%x : %X | %X | %X | %X | %X | %X | %X | %X\n",
     1512            (page_id << 10) + (line <<3 ),
     1513            hal_remote_l32( base_xp + ((line<<5)      ) ),
     1514            hal_remote_l32( base_xp + ((line<<5) + 4  ) ),
     1515            hal_remote_l32( base_xp + ((line<<5) + 8  ) ),
     1516            hal_remote_l32( base_xp + ((line<<5) + 12 ) ),
     1517            hal_remote_l32( base_xp + ((line<<5) + 16 ) ),
     1518            hal_remote_l32( base_xp + ((line<<5) + 20 ) ),
     1519            hal_remote_l32( base_xp + ((line<<5) + 24 ) ),
     1520            hal_remote_l32( base_xp + ((line<<5) + 28 ) ) );
     1521        }
     1522    }
     1523}  // end fatfs_display_fat()
     1524
     1525/////////////////////////////////////
     1526error_t fatfs_check_free_info( void )
     1527{
     1528    error_t       error;
     1529    fatfs_ctx_t * fatfs_ctx_ptr;              // local pointer on fatfs context in cluster 0
     1530    uint32_t      ctx_free_clusters;          // number of free clusters from fatfs context
     1531    uint32_t      ctx_free_cluster_hint;      // free cluster hint from fatfs context
     1532    uint32_t      ioc_free_clusters;          // number of free clusters from fatfs context
     1533    uint32_t      ioc_free_cluster_hint;      // free cluster hint from fatfs context
     1534    uint32_t      fs_info_lba;                // lba of FS_INFO sector on IOC device
     1535    uint8_t     * fs_info_buffer;             // local pointer on FS_INFO buffer in cluster 0
     1536    xptr_t        fs_info_buffer_xp;          // extended pointer on FS_INFO buffer in cluster 0
     1537    uint8_t       tmp_buf[512];               // 512 bytes temporary buffer
     1538    xptr_t        tmp_buf_xp;                 // extended pointer on temporary buffer
     1539
     1540#if DEBUG_FATFS_SYNC_FSINFO
    19501541uint32_t   cycle = (uint32_t)hal_get_cycles();
    19511542thread_t * this  = CURRENT_THREAD;
    1952 vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
    1953 if( DEBUG_FATFS_NEW_DENTRY < cycle )
     1543if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1544printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
     1545__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1546#endif
     1547
     1548    // get pointer on fatfs context in cluster 0
     1549    fatfs_ctx_ptr = hal_remote_lpt( XPTR( 0 , &fs_context[FS_TYPE_FATFS].extend ) );
     1550
     1551    // get "free_clusters" and "free_cluster_hint" from fatfs context in cluster 0
     1552    ctx_free_clusters     = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_clusters ) );
     1553    ctx_free_cluster_hint = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_cluster_hint ) );
     1554
     1555    // get fs_info_lba
     1556    fs_info_lba = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->fs_info_lba ) );
     1557
     1558    // build extended pointer on temporary buffer
     1559    tmp_buf_xp = XPTR( local_cxy , tmp_buf );
     1560
     1561    // copy FS_INFO sector from IOC to local buffer
     1562    error = dev_ioc_sync_read( tmp_buf_xp , fs_info_lba , 1 );
     1563
     1564    if ( error )
     1565    {
     1566        printk("\n[ERROR] in %s : cannot access FS_INFO on IOC device\n", __FUNCTION__ );
     1567        return -1;
     1568    }
     1569
     1570    // get current values of "free_clusters" and "free_cluster_hint" from FS_INFO on IOC
     1571    ioc_free_clusters     = fatfs_get_remote_record( FS_FREE_CLUSTERS     , tmp_buf_xp );
     1572    ioc_free_cluster_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , tmp_buf_xp );
     1573
     1574#if DEBUG_FATFS_SYNC_FSINFO
     1575if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1576printk("\n[%s] thread[%x,%x] / ctx_free %x / ioc_free %x / ctx_hint %x / ioc_hint %x\n",
     1577__FUNCTION__ , this->process->pid, this->trdid,
     1578ctx_free_clusters, ioc_free_clusters, ctx_free_cluster_hint, ioc_free_cluster_hint );
     1579#endif
     1580
     1581    // check values
     1582    if( (ioc_free_clusters     != ctx_free_clusters) ||
     1583        (ioc_free_cluster_hint != ctx_free_cluster_hint) )
     1584    {
     1585        printk("\n[WARNING] in %s : unconsistent free clusters info\n"
     1586        " ioc_free %x / ctx_free %x / ioc_hint %x / ctx_hint %x\n",
     1587        __FUNCTION__, ioc_free_clusters, ctx_free_clusters,
     1588        ioc_free_cluster_hint, ctx_free_cluster_hint );
     1589
     1590        // get pointers on FS_INFO buffer in cluster 0
     1591        fs_info_buffer    = hal_remote_lpt( XPTR( 0 , &fatfs_ctx_ptr->fs_info_buffer ) );
     1592        fs_info_buffer_xp = XPTR( 0 , fs_info_buffer );
     1593
     1594        // update FS_INFO buffer in cluster 0
     1595        fatfs_set_remote_record(FS_FREE_CLUSTERS    ,fs_info_buffer_xp,ctx_free_clusters );
     1596        fatfs_set_remote_record(FS_FREE_CLUSTER_HINT,fs_info_buffer_xp,ctx_free_cluster_hint);
     1597
     1598        // update the FS_INFO sector on IOC device
     1599        error = dev_ioc_sync_write( fs_info_buffer_xp , fs_info_lba , 1 );
     1600
     1601        if ( error )
     1602        {
     1603            printk("\n[ERROR] in %s : cannot update FS_INFO on IOC device\n", __FUNCTION__ );
     1604            return -1;
     1605        }
     1606    }
     1607
     1608#if DEBUG_FATFS_SYNC_FSINFO
     1609cycle = (uint32_t)hal_get_cycles();
     1610if( DEBUG_FATFS_SYNC_FSINFO < cycle )
     1611printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1612__FUNCTION__ , this->process->pid, this->trdid, cycle );
     1613#endif
     1614
     1615    return 0;
     1616
     1617}  // end fatfs_check_free_info()
     1618
     1619
     1620
     1621
     1622
     1623///////////////////////////////////////////////////////////////////////////////////////
     1624// Generic API : the following functions are called by the kernel VFS
     1625//               and must be defined by all supported file systems.
     1626///////////////////////////////////////////////////////////////////////////////////////
     1627
     1628
     1629/////////////////////////////////////
     1630xptr_t  fatfs_ctx_alloc( cxy_t  cxy )
     1631{
     1632    kmem_req_t    req;
     1633
     1634    // allocate memory from remote cluster
     1635        req.type     = KMEM_KCM;
     1636        req.order    = bits_log2( sizeof(fatfs_ctx_t) );
     1637    req.flags    = AF_KERNEL | AF_ZERO;
     1638 
     1639    return XPTR( cxy , kmem_remote_alloc( cxy , &req ) );
     1640
     1641}  //end faffs_ctx_alloc()
     1642
     1643///////////////////////////////////////////////
     1644error_t  fatfs_ctx_init( xptr_t  fatfs_ctx_xp )
     1645{
     1646    error_t       error;
     1647    kmem_req_t    req;
     1648    cxy_t         cxy;             // FATFS context cluster identifier
     1649    fatfs_ctx_t * fatfs_ctx_ptr;   // local pointer on FATFS context
     1650    uint8_t     * buffer;          // local pointer on 512 bytes buffer
     1651    xptr_t        buffer_xp;       // extended pointer on 512 bytes buffer
     1652    xptr_t        fat_mapper_xp;   // extended pointer on FAT mapper
     1653    mapper_t    * fat_mapper;      // local pointer on FAT mapper
     1654
     1655    // get FATFS context cluster and local pointer
     1656    cxy           = GET_CXY( fatfs_ctx_xp );       
     1657    fatfs_ctx_ptr = GET_PTR( fatfs_ctx_xp );
     1658   
     1659#if DEBUG_FATFS_CTX_INIT
     1660uint32_t   cycle = (uint32_t)hal_get_cycles();
     1661thread_t * this  = CURRENT_THREAD;
     1662if( DEBUG_FATFS_CTX_INIT < cycle )
     1663printk("\n[%s] thread[%x,%x] enter for fatfs_ctx (%x,%x) / cycle %d\n",
     1664__FUNCTION__ , this->process->pid, this->trdid, cxy, fatfs_ctx_ptr , cycle );
     1665#endif
     1666
     1667    // allocate a 512 bytes buffer in remote cluster, used to store
     1668    // temporarily the BOOT sector, and permanently the FS_INFO sector
     1669        req.type    = KMEM_KCM;
     1670    req.order   = 9;                    // 512 bytes
     1671    req.flags   = AF_KERNEL | AF_ZERO;
     1672        buffer      = kmem_remote_alloc( cxy , &req );
     1673
     1674    if( buffer == NULL )
     1675    {
     1676        printk("\n[PANIC] in %s : cannot allocate buffer in cluster %x\n",
     1677        __FUNCTION__ , cxy );
     1678        return -1;
     1679    }
     1680     
     1681    // build extended pointer on buffer
     1682    buffer_xp = XPTR( cxy , buffer );
     1683
     1684    // load the BOOT record from device
     1685    error = dev_ioc_sync_read( buffer_xp , 0 , 1 );
     1686
     1687    if ( error )
     1688    {
     1689        printk("\n[PANIC] in %s : cannot access boot record\n", __FUNCTION__ );
     1690        return -1;
     1691    }
     1692
     1693#if (DEBUG_FATFS_CTX_INIT & 0x1)
     1694uint8_t bs[256];
     1695hal_remote_memcpy( XPTR( local_cxy , bs ) , buffer_xp , 256 );
     1696if( DEBUG_FATFS_CTX_INIT < cycle )
     1697putb( "boot record", bs , 256 );
     1698#endif
     1699
     1700    // get sector size from boot record
     1701    uint32_t sector_size = fatfs_get_remote_record( BPB_BYTSPERSEC , buffer_xp );
     1702
     1703    if ( sector_size != 512 )
     1704    {
     1705        printk("\n[PANIC] in %s : sector size must be 512 bytes\n", __FUNCTION__ );
     1706        return -1;
     1707    }
     1708
     1709    // get cluster size from boot record
     1710    uint32_t nb_sectors = fatfs_get_remote_record( BPB_SECPERCLUS , buffer_xp );
     1711
     1712    if ( nb_sectors != 8 )
     1713    {
     1714        printk("\n[PANIC] in %s : cluster size must be 8 sectors\n", __FUNCTION__ );
     1715        return -1;
     1716    }
     1717
     1718    // get number of FAT copies from boot record
     1719    uint32_t nb_fats = fatfs_get_remote_record( BPB_NUMFATS , buffer_xp );
     1720
     1721    if ( nb_fats != 1 )
     1722    {
     1723        printk("\n[PANIC] in %s : number of FAT copies must be 1\n", __FUNCTION__ );
     1724        return -1;
     1725    }
     1726
     1727    // get number of sectors in FAT from boot record
     1728    uint32_t fat_sectors = fatfs_get_remote_record( BPB_FAT32_FATSZ32 , buffer_xp );
     1729
     1730    if ( (fat_sectors & 0xF) != 0 )
     1731    {
     1732        printk("\n[PANIC] in %s : FAT size not multiple of 16 sectors\n", __FUNCTION__ );
     1733        return -1;
     1734    }
     1735
     1736    // get root cluster from boot record
     1737    uint32_t root_cluster = fatfs_get_remote_record( BPB_FAT32_ROOTCLUS , buffer_xp );
     1738
     1739    if ( root_cluster != 2 )
     1740    {
     1741        printk("\n[PANIC] in %s : root cluster index must be 2\n", __FUNCTION__ );
     1742        return -1;
     1743    }
     1744
     1745    // get FAT lba from boot record
     1746    uint32_t fat_lba = fatfs_get_remote_record( BPB_RSVDSECCNT , buffer_xp );
     1747
     1748    // get FS_INFO sector lba from boot record
     1749    uint32_t fs_info_lba = fatfs_get_remote_record( BPB_FAT32_FSINFO , buffer_xp );
     1750
     1751    // load the FS_INFO record from device
     1752    error = dev_ioc_sync_read( buffer_xp , fs_info_lba , 1 );
     1753
     1754    if ( error )
     1755    {
     1756        printk("\n[PANIC] in %s : cannot access FS_INFO record\n", __FUNCTION__ );
     1757        return -1;
     1758    }
     1759
     1760    // get free_clusters number from FS_INFO record
     1761    uint32_t free_clusters = fatfs_get_remote_record( FS_FREE_CLUSTERS , buffer_xp );
     1762
     1763    if ( free_clusters >= fat_sectors << 7 )
     1764    {
     1765        printk("\n[PANIC] in %s : unconsistent free_clusters\n", __FUNCTION__ );
     1766        return -1;
     1767    }
     1768
     1769    // get free_cluster_hint from FS_INFO record
     1770    uint32_t free_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , buffer_xp );
     1771
     1772    if ( free_hint >= fat_sectors << 7 )
     1773    {
     1774        printk("\n[PANIC] in %s : unconsistent free_cluster_hint\n", __FUNCTION__ );
     1775        return -1;
     1776    }
     1777
     1778    // allocate a mapper for the FAT in remote cluster
     1779    fat_mapper_xp  = mapper_create( cxy , FS_TYPE_FATFS );
     1780
     1781    // get local pointer on FAT mapper
     1782    fat_mapper = GET_PTR( fat_mapper_xp );
     1783
     1784    if ( fat_mapper == NULL )
     1785    {
     1786        printk("\n[PANIC] in %s : no memory for FAT mapper in cluster %x\n",
     1787        __FUNCTION__ , cxy );
     1788        return -1;
     1789    }
     1790
     1791#if (DEBUG_FATFS_CTX_INIT & 0x1)
     1792if( DEBUG_FATFS_CTX_INIT < cycle )
     1793printk("\n[%s] sector_size %d / nb_sectors %d / fat_sectors %x / hint %x\n",
     1794__FUNCTION__, sector_size, nb_sectors, fat_sectors, free_hint );
     1795#endif
     1796
     1797    // the inode field is NULL for the FAT mapper
     1798    hal_remote_spt( XPTR( cxy , &fat_mapper->inode ) , NULL );
     1799
     1800    // initialize the FATFS context
     1801    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->fat_begin_lba       ), fat_lba );
     1802    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->fat_sectors_count   ), fat_sectors );
     1803    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->bytes_per_sector    ), sector_size );
     1804    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->sectors_per_cluster ), nb_sectors );
     1805    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->cluster_begin_lba   ), fat_lba + fat_sectors );
     1806    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->root_dir_cluster    ), 2 );
     1807    hal_remote_spt( XPTR( cxy , &fatfs_ctx_ptr->fat_mapper          ), fat_mapper );
     1808    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->fs_info_lba         ), fs_info_lba );
     1809    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->free_clusters       ), free_clusters );
     1810    hal_remote_s32( XPTR( cxy , &fatfs_ctx_ptr->free_cluster_hint   ), free_hint );
     1811    hal_remote_spt( XPTR( cxy , &fatfs_ctx_ptr->fs_info_buffer      ), buffer );
     1812
     1813    // initialize FATFS lock
     1814    remote_rwlock_init( XPTR( cxy , &fatfs_ctx_ptr->lock ) , LOCK_FATFS_FAT );
     1815
     1816#if DEBUG_FATFS_CTX_INIT
     1817if( DEBUG_FATFS_CTX_INIT < cycle )
     1818printk("\n[%s]  thread[%x,%x] exit for fatfs_ctx (%x,%x)\n",
     1819__FUNCTION__, this->process->pid, this->trdid, cxy, fatfs_ctx_ptr );
     1820#endif
     1821
     1822        return 0;
     1823
     1824}  // end fatfs_ctx_init()
     1825
     1826//////////////////////////////////////////////
     1827void fatfs_ctx_destroy( xptr_t  fatfs_ctx_xp )
     1828{
     1829    kmem_req_t   req;
     1830    mapper_t   * fat_mapper;
     1831    uint8_t    * fs_info_buffer;
     1832
     1833    // get FATFS context cluster and local pointer
     1834    fatfs_ctx_t * fatfs_ctx_ptr = GET_PTR( fatfs_ctx_xp );
     1835    cxy_t         fatfs_ctx_cxy = GET_CXY( fatfs_ctx_xp );
     1836
     1837    // get pointer on FAT mapper
     1838    fat_mapper = hal_remote_lpt( XPTR( fatfs_ctx_cxy , &fatfs_ctx_ptr->fat_mapper ) );
     1839
     1840    // release FAT mapper
     1841    mapper_destroy( XPTR( fatfs_ctx_cxy , fat_mapper ) );
     1842
     1843    // get pointer on FS_INFO buffer
     1844    fs_info_buffer = hal_remote_lpt( XPTR( fatfs_ctx_cxy , &fatfs_ctx_ptr->fs_info_buffer ) );
     1845
     1846    // release FS_INFO buffer
     1847    req.type = KMEM_KCM;
     1848    req.ptr  = fs_info_buffer;
     1849    kmem_remote_free( fatfs_ctx_cxy , &req );
     1850
     1851    // release FATFS context descriptor
     1852    req.type = KMEM_KCM;
     1853    req.ptr  = fatfs_ctx_ptr;
     1854    kmem_remote_free( fatfs_ctx_cxy , &req );
     1855
     1856}  // end fatfs_ctx_destroy()
     1857
     1858/////////////////////////////////////////////////////////
     1859error_t fatfs_add_dentry( xptr_t         parent_inode_xp,
     1860                          vfs_dentry_t * dentry_ptr )
     1861{
     1862    error_t       error;
     1863    vfs_inode_t * parent_inode_ptr;   // parent inode local pointer
     1864    cxy_t         parent_cxy;         // pparent inode cluster
     1865    xptr_t        child_inode_xp;     // extended pointer on child inode
     1866    cxy_t         child_cxy;          // child inode cluster
     1867    vfs_inode_t * child_inode_ptr;    // child inode local pointer
     1868    uint32_t      length;             // dentry name length
     1869    uint32_t      nb_lfn;             // number or required LFN
     1870    char          sfn[11];            // buffer for SFN name
     1871    uint8_t       checksum;           // name checksum
     1872    mapper_t    * mapper_ptr;         // local pointer on parent directory mapper
     1873    xptr_t        mapper_xp;          // extended pointer on parent directory mapper
     1874    uint32_t      size;               // child inode size
     1875    uint32_t      type;               // child inode type
     1876    void        * extend;             // child inode extension
     1877    uint32_t      cluster_id;         // child inode first cluster_id in FATFS
     1878
     1879    char          child_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1880
     1881    uint8_t       buf[32];            // local buffer for one FAT32 directory entry
     1882 
     1883// check arguments
     1884assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     1885assert( (dentry_ptr      != NULL)      , "dentry_ptr argument is NULL\n" );
     1886
     1887    // get directory inode cluster and local pointer
     1888    parent_cxy       = GET_CXY( parent_inode_xp );
     1889    parent_inode_ptr = GET_PTR( parent_inode_xp );
     1890
     1891    // get extended pointers on child inode
     1892    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     1893    child_cxy       = GET_CXY( child_inode_xp );
     1894    child_inode_ptr = GET_PTR( child_inode_xp );
     1895
     1896    // get a local copy of the child name
     1897    vfs_inode_get_name( child_inode_xp  , child_name );
     1898
     1899#if DEBUG_FATFS_ADD_DENTRY
     1900uint32_t   cycle = (uint32_t)hal_get_cycles();
     1901thread_t * this  = CURRENT_THREAD;
     1902char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     1903vfs_inode_get_name( parent_inode_xp , parent_name );
     1904if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1905printk("\n[%s]  thread[%x,%x] enter for <%s> in <%s> directory / cycle %d\n",
     1906__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle );
     1907#endif
     1908
     1909    // get pointers on parent directory mapper
     1910    mapper_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     1911    mapper_xp  = XPTR( parent_cxy , mapper_ptr );
     1912
     1913#if (DEBUG_FATFS_ADD_DENTRY & 1)
     1914mapper_display_page( mapper_xp , 0 , 512 );
     1915#endif
     1916
     1917    // get relevant infos from child inode
     1918    type       = hal_remote_l32( XPTR( child_cxy , &child_inode_ptr->type ) );
     1919    size       = hal_remote_l32( XPTR( child_cxy , &child_inode_ptr->size ) );
     1920    extend     = hal_remote_lpt( XPTR( child_cxy , &child_inode_ptr->extend ) );
     1921    cluster_id = (uint32_t)(intptr_t)extend;
     1922
     1923    // analyse child name
     1924    error = fatfs_name_format( child_name,
     1925                               &length,
     1926                               &nb_lfn,
     1927                               sfn,
     1928                               &checksum );
     1929    if ( error )
     1930    {
     1931        printk("\n[ERROR] in %s : dentry name > 31 bytes\n", __FUNCTION__ );
     1932        return -1;
     1933    }
     1934                               
     1935    // Search end of directory with two embedded loops:
     1936    // - scan the pages in the mapper
     1937    // - scan the entries in each page to find NO_MORE_ENTRY
     1938
     1939    xptr_t     page_xp;                 // extended pointer on page descriptor
     1940    xptr_t     base_xp;                 // extended pointer on page base
     1941
     1942    // initialise loop variables
     1943    uint32_t   page_id = 0;             // page index in mapper
     1944    uint32_t   offset  = 0;             // position in page
     1945    uint32_t   found   = 0;             // NO_MORE_ENTRY found
     1946
     1947    // loop on pages in mapper
     1948    while ( found == 0 )
     1949    {
     1950        // get extended pointer on page descriptor in mapper
     1951        page_xp  = mapper_get_page( mapper_xp , page_id );
     1952
     1953        if ( page_xp == XPTR_NULL )
     1954        {
     1955            printk("\n[ERROR] in %s : cannot extend directory mapper\n",
     1956            __FUNCTION__ );
     1957            return -1;
     1958        }
     1959       
     1960        // get pointer on page base
     1961        base_xp = ppm_page2base( page_xp );
     1962
     1963        // loop on directory entries in this page
     1964        while ( (offset < 4096) && (found == 0) )
     1965        {
     1966            if ( fatfs_get_remote_record( LDIR_ORD, (base_xp + offset) ) == NO_MORE_ENTRY )
     1967            {
     1968                found = 1;
     1969            } 
     1970            else
     1971            {
     1972                offset = offset + 32;
     1973            }
     1974        }  // end loop on entries
     1975
     1976        if ( found == 0 )
     1977        {
     1978            page_id++;
     1979            offset = 0;
     1980        }
     1981    }  // end loop on pages
     1982
     1983#if (DEBUG_FATFS_ADD_DENTRY & 1)
     1984if( DEBUG_FATFS_ADD_DENTRY < cycle )
     1985printk("\n[%s]  thread[%x,%x] found NO_MORE_ENTRY : page_id %d / offset %d\n",
     1986__FUNCTION__, this->process->pid, this->trdid, page_id, offset );
     1987#endif
     1988
     1989    // Modify the directory mapper: depending on the name length,
     1990    // the new child requires to write (3, 4, or 5) directory entries.
     1991    // We build one complete directory entry in a local buffer
     1992    // before copying it the remote mapper. We use use a 5 steps FSM
     1993    // (one state per entry to be written), that is traversed as :
     1994    // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE
     1995    // At most two pages are modified:
     1996    // - the page containing the NO_MORE_ENTRY is always modified
     1997    // - the following page can be modified if the name spread on two pages.
     1998
     1999    uint32_t step;          // FSM state
     2000
     2001    if      ( nb_lfn == 1 ) step = 3;
     2002    else if ( nb_lfn == 2 ) step = 4;
     2003    else if ( nb_lfn == 3 ) step = 5;
     2004   
     2005    uint32_t   i;           // byte index in one 32 bytes directory
     2006    uint32_t   c;           // character index in name
     2007
     2008    while ( step )   
     2009    {
     2010        // this block is only executed when the new name spread
     2011        // on two pages, and we need to access a new page in mapper
     2012        if ( offset >= 4096 )
     2013        {
     2014            // copy the modified page to IOC device
     2015            error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2016
     2017            if ( error )
     2018            {
     2019                printk("\n[ERROR] in %s : cannot update directory on device\n",
     2020                __FUNCTION__ );
     2021                return -1;
     2022            }
     2023
     2024            // get the next page in directory mapper
     2025            page_xp  = mapper_get_page( mapper_xp , page_id + 1 );
     2026
     2027            if ( page_xp == XPTR_NULL )
     2028            {
     2029                printk("\n[ERROR] in %s : cannot extend directory mapper\n",
     2030                __FUNCTION__ );
     2031                return -1;
     2032            }
     2033       
     2034            // get pointer on page base
     2035            base_xp = ppm_page2base( page_xp );
     2036           
     2037            // update offset
     2038            offset = 0;
     2039        }
     2040
     2041#if (DEBUG_FATFS_ADD_DENTRY & 1)
     2042cycle = (uint32_t)hal_get_cycles();
     2043if( DEBUG_FATFS_ADD_DENTRY < cycle )
     2044printk("\n[%s] FSM step = %d / offset = %x / nb_lfn = %d / cycle %d\n",
     2045__FUNCTION__, step, offset, nb_lfn, cycle );
     2046#endif
     2047
     2048        // write one FATFS directory entry (32 bytes) per iteration
     2049        switch ( step )
     2050        {
     2051            case 5:   // write LFN3 entry
     2052            {
     2053                c = 26;
     2054
     2055                // write 32 bytes in local buf
     2056                for ( i = 0 ; i < 32 ; i++ )
     2057                {
     2058                    if (i == 0)
     2059                    {
     2060                        if ( nb_lfn == 3) buf[i] = 0x43;
     2061                        else              buf[i] = 0x03;
     2062                    }
     2063                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     2064                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     2065                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     2066                              ( c < length ) )
     2067                    {
     2068                                          buf[i] = child_name[c];
     2069                                          c++;
     2070                    }
     2071                    else if (i == 11)     buf[i] = 0x0F;
     2072                    else if (i == 13)     buf[i] = checksum;
     2073                    else                  buf[i] = 0x00;
     2074                }
     2075
     2076                // copy 32 bytes from local buffer to remote mapper
     2077                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2078
     2079                step--;
     2080                break;
     2081            }
     2082            case 4:   // write LFN2 entry 
     2083            {
     2084                c = 13;
     2085
     2086                // write 32 bytes in local buf
     2087                for ( i = 0 ; i < 32 ; i++ )
     2088                {
     2089                    if (i == 0)
     2090                    {
     2091                        if ( nb_lfn == 2) buf[i] = 0x42;
     2092                        else              buf[i] = 0x02;
     2093                    }
     2094                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     2095                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     2096                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     2097                              ( c < length ) )
     2098                    {
     2099                                          buf[i] = child_name[c];
     2100                                          c++;
     2101                    }
     2102                    else if (i == 11)     buf[i] = 0x0F;
     2103                    else if (i == 13)     buf[i] = checksum;
     2104                    else                  buf[i] = 0x00;
     2105                }
     2106
     2107                // copy 32 bytes from local buffer to remote mapper
     2108                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2109
     2110                step--;
     2111                break;
     2112            }
     2113            case 3:   // Write LFN1 entry   
     2114            {
     2115                c = 0;
     2116
     2117                // write 32 bytes in local buf
     2118                for ( i = 0 ; i < 32 ; i++ )
     2119                {
     2120                    if (i == 0)
     2121                    {
     2122                        if ( nb_lfn == 1) buf[i] = 0x41;
     2123                        else              buf[i] = 0x01;
     2124                    }
     2125                    else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   ||
     2126                                ((i >= 14) && (i<=25) && ((i&1)==0))   ||
     2127                                ((i >= 28) && (i<=31) && ((i&1)==0)) ) &&
     2128                              ( c < length ) )
     2129                    {
     2130                                          buf[i] = child_name[c];
     2131                                          c++;
     2132                    }
     2133                    else if (i == 11)     buf[i] = 0x0F;
     2134                    else if (i == 13)     buf[i] = checksum;
     2135                    else                  buf[i] = 0x00;
     2136                }
     2137
     2138                // copy 32 bytes from local buffer to remote mapper
     2139                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2140
     2141                step--;
     2142                break;
     2143            }
     2144            case 2:   // write NORMAL entry     
     2145            {
     2146                // write 32 bytes in local buf
     2147                for ( i = 0 ; i < 32 ; i++ )
     2148                {
     2149                    if      ( i < 11 )                               // 8.3 SFN
     2150                    {
     2151                                          buf[i] = sfn[i];
     2152                    }
     2153                    else if (i == 11)                                // ATTR
     2154                    {
     2155                        if (type == INODE_TYPE_DIR)  buf[i] = 0x10;
     2156                        else                         buf[i] = 0x20;
     2157                    }
     2158                    else if (i == 20)     buf[i] = cluster_id>>16;   // cluster.B2
     2159                    else if (i == 21)     buf[i] = cluster_id>>24;   // cluster.B3
     2160                    else if (i == 26)     buf[i] = cluster_id>>0;    // cluster.B0
     2161                    else if (i == 27)     buf[i] = cluster_id>>8;    // cluster.B1
     2162                    else if (i == 28)     buf[i] = size>>0;          // size.B0
     2163                    else if (i == 29)     buf[i] = size>>8;          // size.B1
     2164                    else if (i == 30)     buf[i] = size>>16;         // size.B2
     2165                    else if (i == 31)     buf[i] = size>>24;         // size.B3
     2166                    else                  buf[i] = 0x00;
     2167                }
     2168
     2169                // copy 32 bytes from local buffer to remote mapper
     2170                hal_remote_memcpy( base_xp + offset , XPTR( local_cxy  , buf ) , 32 );
     2171
     2172                // set the dentry "extend" field
     2173                hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->extend ),
     2174                                (void *)(intptr_t)(((page_id << 12) + offset) >> 5 ) );
     2175                step--;
     2176                break;
     2177            }
     2178            case 1:   // write NOMORE entry 
     2179            {
     2180                hal_remote_s32( base_xp + offset , 0 );
     2181
     2182                step--;
     2183                break;
     2184            }
     2185
     2186        } // end switch step
     2187
     2188        offset += 32;
     2189
     2190    } // end while     
     2191
     2192    // copy the modified page to the IOC device
     2193    error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2194
     2195    if ( error )
     2196    {
     2197        printk("\n[ERROR] in %s : cannot update directory on device\n",
     2198        __FUNCTION__ );
     2199        return -1;
     2200    }
     2201
     2202#if DEBUG_FATFS_ADD_DENTRY
     2203cycle = (uint32_t)hal_get_cycles();
     2204if( DEBUG_FATFS_ADD_DENTRY < cycle )
     2205printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> directory\n",
     2206__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name );
     2207#endif
     2208
     2209#if (DEBUG_FATFS_ADD_DENTRY & 1)
     2210mapper_display_page( mapper_xp , 0 , 512 );
     2211#endif
     2212
     2213    return 0;
     2214
     2215}  // end fatfs_add_dentry()
     2216
     2217////////////////////////////////////////////////////////////
     2218error_t fatfs_remove_dentry( xptr_t         parent_inode_xp,
     2219                             vfs_dentry_t * dentry_ptr )
     2220{
     2221    error_t       error;
     2222    vfs_inode_t * parent_inode_ptr;   // parent inode local pointer
     2223    cxy_t         parent_cxy;         // pparent inode cluster
     2224    xptr_t        child_inode_xp;     // extended pointer on child inode
     2225    cxy_t         child_cxy;          // child inode cluster
     2226    vfs_inode_t * child_inode_ptr;    // child inode local pointer
     2227    xptr_t        mapper_xp;          // extended pointer on mapper
     2228    mapper_t    * mapper_ptr;         // local pointer on mapper
     2229    xptr_t        page_xp;            // extended pointer on mapper page descriptor
     2230    xptr_t        base_xp;            // extended pointer on mapper page base
     2231    uint32_t      dentry_id;          // FAT32 directory entry index
     2232    uint32_t      page_id;            // page index in directory mapper
     2233    uint32_t      offset;             // offset in this mapper page
     2234
     2235    char          child_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2236
     2237// check arguments
     2238assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     2239assert( (dentry_ptr      != NULL)      , "dentry_ptr argument is NULL\n" );
     2240
     2241    // get directory inode cluster and local pointer
     2242    parent_cxy       = GET_CXY( parent_inode_xp );
     2243    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2244
     2245    // get extended pointers on child inode
     2246    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2247    child_cxy       = GET_CXY( child_inode_xp );
     2248    child_inode_ptr = GET_PTR( child_inode_xp );
     2249
     2250    // get a local copy of the child name
     2251    vfs_inode_get_name( child_inode_xp  , child_name );
     2252
     2253#if DEBUG_FATFS_REMOVE_DENTRY
     2254uint32_t   cycle = (uint32_t)hal_get_cycles();
     2255thread_t * this  = CURRENT_THREAD;
     2256char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2257vfs_inode_get_name( parent_inode_xp , parent_name );
     2258if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     2259printk("\n[%s]  thread[%x,%x] enter for <%s> in <%s> directory / cycle %d\n",
     2260__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle );
     2261#endif
     2262
     2263    // get pointers on directory mapper
     2264    mapper_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     2265    mapper_xp  = XPTR( parent_cxy , mapper_ptr );
     2266
     2267    // compute number of LFN entries
     2268    uint32_t nb_lfn;
     2269    uint32_t name_length = strlen( child_name );
     2270
     2271    if      ( name_length <= 13 ) nb_lfn  = 1;
     2272    else if ( name_length <= 26 ) nb_lfn  = 2;
     2273    else                          nb_lfn  = 3;
     2274
     2275    // We must invalidate (2,3,4) 32 bytes entries:
     2276    // - the NORMAL entry, registered in dentry->extend.
     2277    // - the (1,2,3) preceding LFN entries.
     2278    // At most two pages are modified:
     2279    // - the page containing the NORMAL entry is always modified.
     2280    // - the preceding page is modified when the name spread on two pages.
     2281
     2282    // get NORMAL entry index from dentry extension
     2283    dentry_id  = (uint32_t)(intptr_t)hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->extend ) );
     2284
     2285    // get page index and offset in parent directory mapper
     2286    page_id  = dentry_id >> 7;
     2287    offset   = (dentry_id & 0x7F)<<5;
     2288
     2289#if DEBUG_FATFS_REMOVE_DENTRY & 1
     2290if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     2291printk("\n[%s] dentry_id %x / page_id %x / offset %x\n",
     2292__FUNCTION__, dentry_id, page_id, offset );
     2293#endif
     2294
     2295    // get extended pointer on page descriptor
     2296    page_xp  = mapper_get_page( mapper_xp , page_id );
     2297
     2298    if ( page_xp == XPTR_NULL )
     2299    {
     2300        printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
     2301        return -1;
     2302    }
     2303       
     2304    // get extended pointer on page base
     2305    base_xp = ppm_page2base( page_xp );
     2306
     2307    // invalidate NORMAL entry in directory cache
     2308    hal_remote_sb( base_xp + offset , 0xE5 );
     2309
     2310    // invalidate LFN entries
     2311    while ( nb_lfn )
     2312    {
     2313        // this block is only executed when the removed name
     2314        // spread on two mapper pages
     2315        if (offset == 0)  // we must load page (page_id - 1)
     2316        {
     2317            // copy the modified page to the IOC device
     2318            error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2319
     2320            if ( error )
     2321            {
     2322                printk("\n[ERROR] in %s : cannot update directory on device\n",
     2323                __FUNCTION__ );
     2324                return -1;
     2325            }
     2326
     2327            // get extended pointer on page descriptor
     2328            page_xp  = mapper_get_page( mapper_xp , page_id );
     2329
     2330            if ( page_xp == XPTR_NULL )
     2331            {
     2332                printk("\n[ERROR] in %s : cannot access directory mapper\n", __FUNCTION__ );
     2333                return -1;
     2334            }
     2335       
     2336            // get extended pointer on page base
     2337            base_xp = ppm_page2base( page_xp );
     2338
     2339            // update offset
     2340            offset = 4096;
     2341        }
     2342
     2343        offset = offset - 32;
     2344
     2345// check for LFN entry
     2346assert( (fatfs_get_remote_record( DIR_ATTR, base_xp + offset ) == ATTR_LONG_NAME_MASK ),
     2347"this directory entry must be a LFN\n");
     2348
     2349        // invalidate LFN entry
     2350        hal_remote_sb( base_xp + offset , 0xE5 );
     2351
     2352        nb_lfn--;
     2353    }     
     2354
     2355    // copy the modified page to the IOC device
     2356    error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );   
     2357   
     2358    if ( error )
     2359    {
     2360        printk("\n[ERROR] in %s : cannot update directory on device\n",
     2361        __FUNCTION__ );
     2362        return -1;
     2363    }
     2364
     2365#if DEBUG_FATFS_REMOVE_DENTRY
     2366cycle = (uint32_t)hal_get_cycles();
     2367if( DEBUG_FATFS_REMOVE_DENTRY < cycle )
     2368printk("\n[%s] thread[%x,%x] exit for <%s> in <%s> directory\n",
     2369__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name );
     2370#endif
     2371
     2372    return 0;
     2373
     2374}  // end fatfs_remove_dentry
     2375
     2376/////////////////////////////////////////////////////////////////////
     2377error_t fatfs_new_dentry_from_mapper( xptr_t         parent_inode_xp,
     2378                                      vfs_dentry_t * dentry_ptr )
     2379{
     2380    uint32_t       cluster_id;        // directory entry first FATFS cluster
     2381    uint32_t       size;              // directory entry size
     2382    bool_t         is_dir;            // directory entry type (file/dir)
     2383    cxy_t          parent_cxy;        // parent inode cluster 
     2384    vfs_inode_t  * parent_inode_ptr;  // parent inode local pointer
     2385    mapper_t     * parent_mapper;     // pointer on parent directory mapper
     2386    xptr_t         child_inode_xp;    // extended pointer on child inode
     2387    cxy_t          child_cxy;         // child inode cluster 
     2388    vfs_inode_t  * child_inode_ptr;   // child inode local pointer
     2389    error_t        error;
     2390
     2391    uint8_t        buf[32];           // FAT32 directory entry local copy
     2392
     2393    char           parent_name[CONFIG_VFS_MAX_NAME_LENGTH];     // local parent name copy
     2394    char           child_name[CONFIG_VFS_MAX_NAME_LENGTH];      // local child name copy
     2395
     2396// check arguments
     2397assert( (parent_inode_xp != XPTR_NULL)  , "parent_inode_xp is NULL\n" );
     2398assert( (dentry_ptr      != NULL ) , "dentry_ptr is NULL\n" );
     2399
     2400    // get parent inode cluster and local pointer
     2401    parent_cxy       = GET_CXY( parent_inode_xp );
     2402    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2403
     2404    // get child inode cluster and pointers
     2405    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2406    child_cxy       = GET_CXY( child_inode_xp );
     2407    child_inode_ptr = GET_PTR( child_inode_xp );
     2408
     2409    // get child and parent names
     2410    vfs_inode_get_name( parent_inode_xp , parent_name );
     2411    vfs_inode_get_name( child_inode_xp  , child_name );
     2412
     2413#if DEBUG_FATFS_NEW_DENTRY_FROM
     2414uint32_t   cycle = (uint32_t)hal_get_cycles();
     2415thread_t * this  = CURRENT_THREAD;
     2416if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle )
    19542417printk("\n[%s]  thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
    1955 __FUNCTION__, this->process->pid, this->trdid, name , parent_name , cycle );
     2418__FUNCTION__, this->process->pid, this->trdid, child_name , parent_name , cycle );
    19562419#endif
    19572420
    19582421    // get local pointer on parent mapper
    1959     mapper = parent_inode->mapper;
    1960 
    1961     // get pointer and index in mapper for searched directory entry
    1962     error  = fatfs_scan_directory( mapper, name , &entry , &index );
    1963 
    1964     // return non fatal error if not found
    1965     if( error )
    1966     {
    1967         vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
    1968         printk("\n[ERROR] in %s : cannot find <%s> entry in <%s> directory mapper\n",
    1969         __FUNCTION__, name , parent_name, name );
    1970         return -1;
    1971     }
    1972  
    1973 
    1974     // get relevant infos from FAT32 directory entry
    1975     cluster = (fatfs_get_record( DIR_FST_CLUS_HI , entry ) << 16) |
    1976               (fatfs_get_record( DIR_FST_CLUS_LO , entry )      ) ;
    1977     is_dir  = (fatfs_get_record( DIR_ATTR        , entry ) & ATTR_DIRECTORY);
    1978     size    =  fatfs_get_record( DIR_FILE_SIZE   , entry );
    1979 
    1980     // scan list of parent dentries to search the parent_inode
    1981     bool_t found = false;
    1982     XLIST_FOREACH( root_xp , iter_xp )
    1983     {
    1984         // get pointers on dentry
    1985         dentry_xp  = XLIST_ELEMENT( iter_xp , vfs_dentry_t , parents );
    1986         dentry_cxy = GET_CXY( dentry_xp );
    1987         dentry_ptr = GET_PTR( dentry_xp );
    1988 
    1989         // get local pointer on current parent directory inode
    1990         vfs_inode_t * current = hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) );
    1991 
    1992         // check if current parent is the searched parent
    1993         if( XPTR( dentry_cxy , current ) == XPTR( local_cxy , parent_inode ) )
    1994         {
    1995             found = true;
    1996             break;
    1997         }
    1998     }
    1999 
    2000     if( found == false )
    2001     {
    2002         vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name );
    2003         printk("\n[ERROR] in %s : cannot find <%s> directory in list of parents for <%s>\n",
    2004         __FUNCTION__, parent_name, name );
    2005         return -1;
    2006     }
     2422    parent_mapper = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     2423
     2424    // try to get pointer and index of directory entry in mapper
     2425    uint8_t      * entry = NULL;
     2426    uint32_t       index = 0;
     2427
     2428    error  = fatfs_scan_directory( XPTR( parent_cxy , parent_mapper ),
     2429                                   child_name,
     2430                                   &entry,
     2431                                   &index );
     2432   
     2433    // an error can be non fatal, for a new (created) entry
     2434    if( error )  return -1;
     2435
     2436    // get local copy of found directory entry
     2437    hal_remote_memcpy( XPTR( local_cxy  , buf ),
     2438                       XPTR( parent_cxy , entry ), 32 );
     2439
     2440    // get relevant infos from directory entry
     2441    cluster_id = (fatfs_get_record( DIR_FST_CLUS_HI , buf ) << 16) |
     2442                 (fatfs_get_record( DIR_FST_CLUS_LO , buf )      ) ;
     2443    is_dir     = (fatfs_get_record( DIR_ATTR        , buf ) & ATTR_DIRECTORY );
     2444    size       =  fatfs_get_record( DIR_FILE_SIZE   , buf );
    20072445
    20082446    // update the child inode "type", "size", and "extend" fields
    20092447    vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE;
    20102448
    2011     hal_remote_s32( XPTR( child_inode_cxy , &child_inode_ptr->type   ) , type );
    2012     hal_remote_s32( XPTR( child_inode_cxy , &child_inode_ptr->size   ) , size );
    2013     hal_remote_s32( XPTR( child_inode_cxy , &child_inode_ptr->extend ) , cluster );
     2449    hal_remote_s32( XPTR( child_cxy , &child_inode_ptr->type   ) , type );
     2450    hal_remote_s32( XPTR( child_cxy , &child_inode_ptr->size   ) , size );
     2451    hal_remote_s32( XPTR( child_cxy , &child_inode_ptr->extend ) , cluster_id );
    20142452
    20152453    // update the dentry "extend" field
    2016     dentry_ptr->extend = (void *)(intptr_t)index;
    2017 
    2018 #if DEBUG_FATFS_NEW_DENTRY
     2454    hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->extend ) , (void *)(intptr_t)index );
     2455
     2456#if DEBUG_FATFS_NEW_DENTRY_FROM
    20192457cycle = (uint32_t)hal_get_cycles();
    2020 if( DEBUG_FATFS_NEW_DENTRY < cycle )
    2021 printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> / cluster_id %x / size %d  / cycle %d\n",
    2022 __FUNCTION__, this->process->pid, this->trdid, name, parent_name, cluster, size,  cycle );
    2023 #endif
    2024 
    2025 
    2026 #if (DEBUG_FATFS_NEW_DENTRY & 1)
    2027 if( DEBUG_FATFS_NEW_DENTRY < cycle )
    2028 {
    2029     fatfs_display_fat( 0 , 0 , 64 );
    2030     fatfs_display_fat( cluster >> 10 ,  (cluster & 0x3FF) , 32 );
    2031 }
     2458if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle )
     2459printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> / cluster_id %x / size %d\n",
     2460__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cluster_id, size );
     2461#endif
     2462
     2463#if (DEBUG_FATFS_NEW_DENTRY_FROM & 1)
     2464if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle )
     2465fatfs_display_fat( cluster_id , 32 );
    20322466#endif
    20332467
    20342468    return 0;
    20352469
    2036 }  // end fatfs_new_dentry()
    2037 
    2038 //////////////////////////////////////////////////
    2039 error_t fatfs_update_dentry( vfs_inode_t  * inode,
    2040                              vfs_dentry_t * dentry,
    2041                              uint32_t       size )
    2042 {
    2043     uint8_t  * entry;    // pointer on FAT32 directory entry (array of 32 bytes)
    2044     uint32_t   index;    // index of FAT32 directory entry in mapper
    2045     mapper_t * mapper;   // pointer on directory mapper
    2046     error_t    error;
    2047 
    2048     char       dir_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2470}  // end fatfs_new_dentry_from_mapper()
     2471
     2472///////////////////////////////////////////////////////////////////
     2473error_t fatfs_new_dentry_to_mapper( xptr_t         parent_inode_xp,
     2474                                    vfs_dentry_t * dentry_ptr )
     2475{
     2476    uint32_t       cluster_id;        // directory entry cluster
     2477    cxy_t          parent_cxy;        // parent inode cluster identifier 
     2478    vfs_inode_t  * parent_inode_ptr;  // child inode local pointer
     2479    xptr_t         child_inode_xp;    // extended pointer on child inode
     2480    cxy_t          child_cxy;         // child inode cluster identifier 
     2481    vfs_inode_t  * child_inode_ptr;   // child inode local pointer
     2482    error_t        error;
     2483
     2484    char           parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2485    char           child_name[CONFIG_VFS_MAX_NAME_LENGTH];
    20492486
    20502487// check arguments
    2051 assert( (inode  != NULL) , "inode is NULL\n" );
    2052 assert( (dentry != NULL) , "dentry is NULL\n" );
     2488assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     2489assert( (dentry_ptr      != NULL)      , "dentry_ptr argument NULL\n" );
     2490
     2491    // get child inode cluster and local pointer
     2492    parent_cxy       = GET_CXY( parent_inode_xp );
     2493    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2494
     2495    // get child inode cluster and pointers
     2496    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2497    child_cxy       = GET_CXY( child_inode_xp );
     2498    child_inode_ptr = GET_PTR( child_inode_xp );
     2499
     2500    // get child and parent names
     2501    vfs_inode_get_name( parent_inode_xp , parent_name );
     2502    vfs_inode_get_name( child_inode_xp  , child_name );
     2503
     2504#if DEBUG_FATFS_NEW_DENTRY_TO_MAP
     2505uint32_t   cycle = (uint32_t)hal_get_cycles();
     2506thread_t * this  = CURRENT_THREAD;
     2507if( DEBUG_FATFS_NEW_DENTRY_TO_MAP < cycle )
     2508printk("\n[%s]  thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n",
     2509__FUNCTION__, this->process->pid, this->trdid, child_name , parent_name , cycle );
     2510#endif
     2511
     2512    // 1. allocate one FATFS cluster (update FAT and FSINFO)
     2513    error = fatfs_cluster_alloc( 0 , &cluster_id );
     2514
     2515    if( error )
     2516    {
     2517        printk("\n[ERROR] in %s : cannot find a free cluster_id\n",
     2518        __FUNCTION__ );
     2519        return -1;
     2520    }
     2521       
     2522    // 2. register cluster_id in inode descriptor
     2523    hal_remote_spt( XPTR( child_cxy , &child_inode_ptr->extend ),
     2524                    (void*)(intptr_t)cluster_id );
     2525   
     2526    // 3. introduce dentry in the directory mapper
     2527    error = fatfs_add_dentry( parent_inode_xp , dentry_ptr );
     2528       
     2529    if( error )
     2530    {
     2531        printk("\n[ERROR] in %s : cannot update parent directory mapper\n",
     2532        __FUNCTION__ );
     2533        // TODO release cluster_id [AG]
     2534        return -1;
     2535    }
     2536
     2537#if DEBUG_FATFS_NEW_DENTRY_TO_MAP
     2538if( DEBUG_FATFS_NEW_DENTRY_TO_MAP < cycle )
     2539printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> / cluster_id %x\n",
     2540__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cluster_id );
     2541#endif
     2542
     2543    return 0;
     2544
     2545}  // end fatfs_new_dentry_to mapper()
     2546
     2547
     2548////////////////////////////////////////////////////////////
     2549error_t fatfs_update_dentry( xptr_t         parent_inode_xp,
     2550                             vfs_dentry_t * dentry_ptr )
     2551{
     2552    cxy_t         parent_cxy;        // parent directory cluster identifier
     2553    vfs_inode_t * parent_inode_ptr;  // extended pointer on parent directory inode
     2554    mapper_t    * parent_mapper_ptr; // local pointer on parent directory mapper
     2555    xptr_t        parent_mapper_xp;  // extended pointer on parent directory mapper
     2556    xptr_t        child_inode_xp;    // extended pointer on child inode
     2557    cxy_t         child_cxy;         // child inode cluster identifier
     2558    vfs_inode_t * child_inode_ptr;   // extended pointer on child inode
     2559
     2560    uint32_t      current_size;      // current size in directory mapper
     2561    uint32_t      new_size;          // new size (from child inode)
     2562   
     2563    uint32_t      entry_id;          // directory entry index in parent directory mapper
     2564    uint32_t      page_id;           // page_index in parent directory mapper
     2565    uint32_t      offset;            // directory entry offset in page
     2566    xptr_t        page_xp;           // extended pointer on page descriptor
     2567    xptr_t        base_xp;           // extended pointer on page base
     2568    xptr_t        entry_xp;          // extended pointer on directory entry
     2569
     2570    error_t       error;
     2571
     2572    char       parent_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2573    char       child_name[CONFIG_VFS_MAX_NAME_LENGTH];
     2574
     2575// check arguments
     2576assert( (parent_inode_xp  != XPTR_NULL) , "parent_inode_xp argument is NULL\n" );
     2577assert( (dentry_ptr       != NULL)      , "dentry_ptr argument is NULL\n" );
     2578
     2579    // get parent directory cluster ans local pointer
     2580    parent_inode_ptr = GET_PTR( parent_inode_xp );
     2581    parent_cxy       = GET_CXY( parent_inode_xp );
     2582
     2583    // get extended pointer on child inode
     2584    child_inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) );
     2585
     2586    // get child and parent names
     2587    vfs_inode_get_name( parent_inode_xp , parent_name );
     2588    vfs_inode_get_name( child_inode_xp  , child_name );
    20532589
    20542590#if DEBUG_FATFS_UPDATE_DENTRY
    20552591uint32_t   cycle = (uint32_t)hal_get_cycles();
    20562592thread_t * this  = CURRENT_THREAD;
    2057 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    20582593if( DEBUG_FATFS_UPDATE_DENTRY < cycle )
    2059 printk("\n[%s]  thread[%x,%x] enter for <%s/%s> / size %d / cycle %d\n",
    2060 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, size, cycle );
    2061 #endif
    2062 
    2063     // get local pointer on mapper
    2064     mapper = inode->mapper;
    2065 
    2066     // get pointer and index in mapper for searched directory entry
    2067     error  = fatfs_scan_directory( mapper, dentry->name , &entry , &index );
    2068 
    2069     if( error )
    2070     {
    2071         vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    2072         printk("\n[ERROR] in %s : cannot find <%s> in parent mapper <%s>\n",
    2073         __FUNCTION__, dentry->name, dir_name );
    2074         return -1;
    2075     }
    2076 
    2077     // get current size value
    2078     uint32_t current_size = fatfs_get_record( DIR_FILE_SIZE , entry );
     2594printk("\n[%s]  thread[%x,%x] enter for <%s> in <%s> / new_size %d / cycle %d\n",
     2595__FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, new_size, cycle );
     2596#endif
     2597
     2598    // get child inode cluster and local pointer
     2599    child_cxy       = GET_CXY( child_inode_xp );
     2600    child_inode_ptr = GET_PTR( child_inode_xp );
     2601 
     2602    // get size from child inode
     2603    new_size = hal_remote_l32( XPTR( child_cxy , &child_inode_ptr->size ) );
     2604 
     2605    // get local and extended pointers on parent directory mapper
     2606    parent_mapper_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_inode_ptr->mapper ) );
     2607    parent_mapper_xp  = XPTR( parent_cxy , parent_mapper_ptr );
     2608
     2609    // get directory entry index from dentry extension
     2610    entry_id = (intptr_t)hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->extend ) );
     2611
     2612    // get page index and offset in parent directory mapper
     2613    page_id  = entry_id >> 7;
     2614    offset   = (entry_id & 0x7F) << 5;
     2615
     2616    // get extended pointers on page descriptor and page base
     2617    page_xp = mapper_get_page( parent_mapper_xp , page_id );     
     2618    base_xp = ppm_page2base( page_xp );
     2619
     2620    // build extended pointer on directory entry
     2621    entry_xp = base_xp + offset;
     2622
     2623    // get current size from directory mapper
     2624    current_size = fatfs_get_remote_record( DIR_FILE_SIZE , entry_xp );
    20792625
    20802626    // update dentry in mapper & device only if required
    2081     if( size != current_size )
     2627    if( new_size != current_size )
    20822628    {
    20832629        // set size field in FAT32 directory entry
    2084         fatfs_set_record( DIR_FILE_SIZE , entry , size );
    2085 
    2086         // get pointer on modified page base
    2087         void * base = (void *)((intptr_t)entry & (~CONFIG_PPM_PAGE_MASK));
    2088 
    2089         // get extended pointer on modified page descriptor
    2090         xptr_t page_xp = ppm_base2page( XPTR( local_cxy , base ) );
    2091 
    2092         // synchronously update the modified page on device
     2630        fatfs_set_remote_record( DIR_FILE_SIZE , entry_xp , new_size );
     2631
     2632        // synchronously update the modified mapper page on device
    20932633        error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
    20942634
    20952635        if( error )
    20962636        {
    2097             vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );
    20982637            printk("\n[ERROR] in %s : cannot update parent directory <%s> on device\n",
    2099             __FUNCTION__, dir_name );
     2638            __FUNCTION__, parent_name );
    21002639            return -1;
    21012640        }
     
    21052644cycle = (uint32_t)hal_get_cycles();
    21062645if( DEBUG_FATFS_UPDATE_DENTRY < cycle )
    2107 printk("\n[%s]  thread[%x,%x] exit / updated size for <%s/%s> / cycle %d\n",
    2108 __FUNCTION__, this->process->pid, this->trdid, dir_name, dentry->name, cycle );
     2646printk("\n[%s]  thread[%x,%x] exit for <%s> in <%s> directory / size %d / cycle %d\n",
     2647__FUNCTION__, this->process->pid, this->trdid, parent_name, child->name, new_size, cycle );
    21092648#endif
    21102649
     
    21682707    {
    21692708        // get one page from mapper
    2170         page_xp = mapper_remote_get_page( mapper_xp , page_id );
     2709        page_xp = mapper_get_page( mapper_xp , page_id );
    21712710
    21722711        if( page_xp == XPTR_NULL) return -1;
     
    22732812}  // end fatfs_get_user_dir()
    22742813
    2275 ///////////////////////////////////////////////
    2276 error_t fatfs_sync_inode( vfs_inode_t * inode )
    2277 {
     2814///////////////////////////////////////////
     2815error_t fatfs_sync_inode( xptr_t inode_xp )
     2816{
     2817    cxy_t         inode_cxy;      // remote inode cluster
     2818    vfs_inode_t * inode_ptr;      // remote inode local pointer
     2819    mapper_t    * mapper;         // remote inode mapper local pointer
     2820    uint32_t      size;           // remote inode size in bytes
     2821    uint32_t      type;           // remote inode type
     2822    xptr_t        rt_xp;          // extended pointer on mapper radix tree
     2823    uint32_t      npages;         // number of pages in mapper
     2824    uint32_t      page_id;        // current page index in mapper
     2825    xptr_t        page_xp;        // extended pointer on current page
     2826    page_t      * page_ptr;       // local pointer on current page
     2827    uint32_t      flags;          // current page flags
     2828    error_t       error;
    22782829
    22792830// check inode pointer and cluster index
    2280 assert( (inode != NULL)                  , "inode pointer undefined\n" );
    2281 assert( (inode->mapper != NULL )         , "mapper pointer undefined\n" );
    2282 assert( (inode->type == INODE_TYPE_FILE) , "inode must be a file\n" );     
     2831assert( (inode_xp != XPTR_NULL)          , "inode pointer undefined\n" );
    22832832
    22842833#if DEBUG_FATFS_SYNC_INODE
     
    22862835uint32_t   cycle = (uint32_t)hal_get_cycles();
    22872836thread_t * this  = CURRENT_THREAD;
    2288 vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
     2837vfs_inode_get_name( inode_xp , name );
    22892838if( DEBUG_FATFS_SYNC_INODE < cycle )
    22902839printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
     
    22922841#endif
    22932842
    2294     error_t    error;
    2295     mapper_t * mapper;
    2296     page_t   * page;
    2297     uint32_t   page_id;
    2298 
    2299     // get mapper from inode
    2300     mapper = inode->mapper;
    2301 
    2302     // compute max number of pages in mapper from file size
    2303     uint32_t size  = inode->size;
    2304     uint32_t pages = size >> CONFIG_PPM_PAGE_SHIFT;
    2305     if( size & CONFIG_PPM_PAGE_MASK ) pages++;
     2843    // get inode cluster and local pointer
     2844    inode_cxy = GET_CXY( inode_xp );
     2845    inode_ptr = GET_PTR( inode_xp );
     2846
     2847    //get inode mapper pointer
     2848    mapper    = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
     2849
     2850assert( (mapper != NULL) , "mapper pointer is NULL\n" );     
     2851
     2852    // get inode type and size
     2853    size = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size ) );
     2854    type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) );
     2855
     2856assert( (type == INODE_TYPE_FILE) , "inode is not a file\n" );     
     2857
     2858    // compute number of pages
     2859    npages = size >> CONFIG_PPM_PAGE_SHIFT;
     2860    if( size & CONFIG_PPM_PAGE_MASK ) npages++;
    23062861         
    2307     // get pointer on mapper radix tree
    2308     grdxt_t * rt = &mapper->rt;
     2862    // build pointers on mapper radix tree
     2863    rt_xp = XPTR( inode_cxy , &mapper->rt );
    23092864
    23102865    // scan all pages
    2311     for( page_id = 0 ; page_id < pages ; page_id++ )
     2866    for( page_id = 0 ; page_id < npages ; page_id++ )
    23122867    {
    23132868        // get page descriptor from mapper
    2314         page = grdxt_lookup( rt , page_id );
     2869        page_xp = grdxt_remote_lookup( rt_xp , page_id );
    23152870
    23162871        // check all existing pages
    2317         if ( page != NULL )
    2318         {
    2319             if ( page->flags & PG_DIRTY )
     2872        if ( page_xp != XPTR_NULL )
     2873        {
     2874            // get page cluster and local pointer
     2875            page_ptr = GET_PTR( page_xp );
     2876
     2877            // get page flags
     2878            flags = hal_remote_l32( XPTR( inode_cxy , &page_ptr->flags ) );
     2879   
     2880            if ( flags & PG_DIRTY )
    23202881            {
    23212882
    23222883#if (DEBUG_FATFS_SYNC_INODE & 1)
    23232884if( DEBUG_FATFS_SYNC_INODE < cycle )
    2324 printk("\n[%s] thread[%x,%x] synchronizes page %d from <%s> mapper to IOC device\n",
     2885printk("\n[%s] thread[%x,%x] synchronizes page %d of <%s> mapper to IOC device\n",
    23252886__FUNCTION__, page_id, name );
    23262887#endif
    2327                 // build extended pointer on page descriptor
    2328                 xptr_t page_xp = XPTR( local_cxy , page );
    2329 
    23302888                // move page from mapper to device
    23312889                error = fatfs_move_page( page_xp , IOC_WRITE );
     
    23422900cycle = (uint32_t)hal_get_cycles();
    23432901if( DEBUG_FATFS_SYNC_INODE < cycle )
    2344 printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n",
    2345 __FUNCTION__ , this->process->pid, this->trdid, name, cycle );
     2902printk("\n[%s] thread[%x,%x] exit for <%s>\n",
     2903__FUNCTION__ , this->process->pid, this->trdid, name );
    23462904#endif
    23472905
     
    23492907
    23502908}  // end fatfs_sync_inode()
    2351 
    2352 
    2353 
    2354 
    2355 
    23562909
    23572910//////////////////////////////
    23582911error_t fatfs_sync_fat( void )
    23592912{
     2913
     2914    fatfs_ctx_t * fatfs_ctx;
     2915    cxy_t         fat_cxy;
     2916    mapper_t    * mapper_ptr;
     2917    xptr_t        mapper_xp;
     2918    uint32_t      start_page_id;
     2919    uint32_t      found_page_id;
     2920    page_t      * page_ptr;
     2921    xptr_t        page_xp;
     2922    uint32_t      flags;
     2923    error_t       error;
    23602924
    23612925#if DEBUG_FATFS_SYNC_FAT
     
    23662930__FUNCTION__ , this->process->pid, this->trdid, cycle );
    23672931#endif
    2368 
    2369     uint32_t   page_id;
    2370     error_t    error;
    2371 
    2372     // get FAT mapper pointers an cluster
    2373     fatfs_ctx_t * fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
    2374     xptr_t        mapper_xp  = fatfs_ctx->fat_mapper_xp;
    2375     cxy_t         mapper_cxy = GET_CXY( mapper_xp );
    2376     mapper_t    * mapper_ptr = GET_PTR( mapper_xp );
    2377 
    2378     // compute max number of 4 Kbytes pages in FAT mapper
    2379     // TODO : this could be improved (see fatfs.h) [AG]
    2380     uint32_t   pages = fatfs_ctx->fat_sectors_count >> 3;
    2381          
     2932   
     2933    // get FAT cluster
     2934    fat_cxy = CONFIG_VFS_ROOT_CXY;
     2935   
     2936    // get FAT mapper pointers 
     2937    fatfs_ctx  = fs_context[FS_TYPE_FATFS].extend;
     2938    mapper_ptr = fatfs_ctx->fat_mapper;
     2939    mapper_xp  = XPTR( fat_cxy , mapper_ptr );
     2940
    23822941    // get pointers on remote FAT mapper radix tree
    23832942    grdxt_t  * rt_ptr = &mapper_ptr->rt;
    2384     xptr_t     rt_xp  = XPTR( mapper_cxy , rt_ptr );
    2385 
    2386     // scan all pages
    2387     for( page_id = 0 ; page_id < pages ; page_id++ )
    2388     {
    2389         // get extended pointer on page descriptor from FAT mapper
    2390         xptr_t page_xp = grdxt_remote_lookup( rt_xp , page_id );
    2391 
    2392         // check all existing pages
    2393         if ( page_xp != XPTR_NULL )
    2394         {
    2395             page_t * page_ptr = GET_PTR( page_xp );
    2396             uint32_t flags    = hal_remote_l32( XPTR( mapper_cxy , &page_ptr->flags ) );
    2397 
    2398             if ( flags & PG_DIRTY )
    2399             {
     2943    xptr_t     rt_xp  = XPTR( fat_cxy , rt_ptr );
     2944
     2945    // initialise page_id
     2946    start_page_id = 0;
     2947
     2948    // scan FAT mapper
     2949    while( 1 )
     2950    {
     2951        // get one page
     2952        page_xp = grdxt_remote_get_first( rt_xp , start_page_id , &found_page_id );
     2953
     2954        // exit loop when no more page found
     2955        if ( page_xp != XPTR_NULL ) break;
     2956
     2957        // get page flags
     2958        page_ptr = GET_PTR( page_xp );
     2959        flags    = hal_remote_l32( XPTR( fat_cxy , &page_ptr->flags ) );
     2960
     2961        if ( flags & PG_DIRTY )
     2962        {
    24002963
    24012964#if (DEBUG_FATFS_SYNC_FAT & 1)
     
    24042967__FUNCTION__, page_id );
    24052968#endif
    2406                 // move page from mapper to device
    2407                 error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
    2408 
    2409                 if ( error )  return -1;
    2410 
    2411                 // reset page dirty flag
    2412                 ppm_page_undo_dirty( page_xp );
    2413             }
    2414         }
     2969            // move page from mapper to device
     2970            error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
     2971
     2972            if ( error )  return -1;
     2973
     2974            // reset page dirty flag
     2975            ppm_page_undo_dirty( page_xp );
     2976        }
     2977
     2978        // update loop variable
     2979        start_page_id = found_page_id + 1;
     2980
    24152981    }  // end loop on pages
    24162982
     
    24182984cycle = (uint32_t)hal_get_cycles();
    24192985if( DEBUG_FATFS_SYNC_FAT < cycle )
    2420 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
    2421 __FUNCTION__ , this->process->pid, this->trdid, cycle );
     2986printk("\n[%s] thread[%x,%x] exit\n",
     2987__FUNCTION__ , this->process->pid, this->trdid );
    24222988#endif
    24232989
     
    24252991
    24262992}  // end fatfs_sync_fat()
    2427 
    2428 ////////////////////////////////////
    2429 error_t fatfs_sync_free_info( void )
    2430 {
    2431     error_t       error;
    2432     fatfs_ctx_t * fatfs_ctx_ptr;              // local pointer on fatfs context in cluster 0
    2433     uint32_t      ctx_free_clusters;          // number of free clusters from fatfs context
    2434     uint32_t      ctx_free_cluster_hint;      // free cluster hint from fatfs context
    2435     uint32_t      ioc_free_clusters;          // number of free clusters from fatfs context
    2436     uint32_t      ioc_free_cluster_hint;      // free cluster hint from fatfs context
    2437     uint32_t      fs_info_lba;                // lba of FS_INFO sector on IOC device
    2438     uint8_t     * fs_info_buffer;             // local pointer on FS_INFO buffer in cluster 0
    2439     xptr_t        fs_info_buffer_xp;          // extended pointer on FS_INFO buffer in cluster 0
    2440     uint8_t       tmp_buf[512];               // 512 bytes temporary buffer
    2441     xptr_t        tmp_buf_xp;                 // extended pointer on temporary buffer
    2442 
    2443 #if DEBUG_FATFS_SYNC_FSINFO
    2444 uint32_t   cycle = (uint32_t)hal_get_cycles();
    2445 thread_t * this  = CURRENT_THREAD;
    2446 if( DEBUG_FATFS_SYNC_FSINFO < cycle )
    2447 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    2448 __FUNCTION__ , this->process->pid, this->trdid, cycle );
    2449 #endif
    2450 
    2451     // get pointer on fatfs context in cluster 0
    2452     fatfs_ctx_ptr = hal_remote_lpt( XPTR( 0 , &fs_context[FS_TYPE_FATFS].extend ) );
    2453 
    2454     // get "free_clusters" and "free_cluster_hint" from fatfs context in cluster 0
    2455     ctx_free_clusters     = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_clusters ) );
    2456     ctx_free_cluster_hint = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->free_cluster_hint ) );
    2457 
    2458     // get fs_info_lba
    2459     fs_info_lba = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->fs_info_lba ) );
    2460 
    2461     // build extended pointer on temporary buffer
    2462     tmp_buf_xp = XPTR( local_cxy , tmp_buf );
    2463 
    2464     // copy FS_INFO sector from IOC to local buffer
    2465     error = dev_ioc_move_data( IOC_SYNC_READ , tmp_buf_xp , fs_info_lba , 1 );
    2466 
    2467     if ( error )
    2468     {
    2469         printk("\n[ERROR] in %s : cannot access FS_INFO on IOC device\n", __FUNCTION__ );
    2470         return -1;
    2471     }
    2472 
    2473     // get current values of "free_clusters" and "free_cluster_hint" from FS_INFO on IOC
    2474     ioc_free_clusters     = fatfs_get_remote_record( FS_FREE_CLUSTERS     , tmp_buf_xp );
    2475     ioc_free_cluster_hint = fatfs_get_remote_record( FS_FREE_CLUSTER_HINT , tmp_buf_xp );
    2476 
    2477 #if DEBUG_FATFS_SYNC_FSINFO
    2478 if( DEBUG_FATFS_SYNC_FSINFO < cycle )
    2479 printk("\n[%s] thread[%x,%x] / ctx_free %x / ioc_free %x / ctx_hint %x / ioc_hint %x\n",
    2480 __FUNCTION__ , this->process->pid, this->trdid,
    2481 ctx_free_clusters, ioc_free_clusters, ctx_free_cluster_hint, ioc_free_cluster_hint );
    2482 #endif
    2483 
    2484     // check values
    2485     if( (ioc_free_clusters     != ctx_free_clusters) ||
    2486         (ioc_free_cluster_hint != ctx_free_cluster_hint) )
    2487     {
    2488         printk("\n[WARNING] in %s : unconsistent free clusters info\n"
    2489         " ioc_free %x / ctx_free %x / ioc_hint %x / ctx_hint %x\n",
    2490         __FUNCTION__, ioc_free_clusters, ctx_free_clusters,
    2491         ioc_free_cluster_hint, ctx_free_cluster_hint );
    2492 
    2493         // get pointers on FS_INFO buffer in cluster 0
    2494         fs_info_buffer    = hal_remote_lpt( XPTR( 0 , &fatfs_ctx_ptr->fs_info_buffer ) );
    2495         fs_info_buffer_xp = XPTR( 0 , fs_info_buffer );
    2496 
    2497         // update FS_INFO buffer in cluster 0
    2498         fatfs_set_remote_record(FS_FREE_CLUSTERS    ,fs_info_buffer_xp,ctx_free_clusters );
    2499         fatfs_set_remote_record(FS_FREE_CLUSTER_HINT,fs_info_buffer_xp,ctx_free_cluster_hint);
    2500 
    2501         // update the FS_INFO sector on IOC device
    2502         error = dev_ioc_move_data( IOC_SYNC_WRITE , fs_info_buffer_xp , fs_info_lba , 1 );
    2503 
    2504         if ( error )
    2505         {
    2506             printk("\n[ERROR] in %s : cannot update FS_INFO on IOC device\n", __FUNCTION__ );
    2507             return -1;
    2508         }
    2509     }
    2510 
    2511 #if DEBUG_FATFS_SYNC_FSINFO
    2512 cycle = (uint32_t)hal_get_cycles();
    2513 if( DEBUG_FATFS_SYNC_FSINFO < cycle )
    2514 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
    2515 __FUNCTION__ , this->process->pid, this->trdid, cycle );
    2516 #endif
    2517 
    2518     return 0;
    2519 
    2520 }  // end fatfs_sync_free_info()
    2521 
    2522 //////////////////////////////////////////////////////////
    2523 error_t fatfs_cluster_alloc( uint32_t * searched_cluster )
    2524 {
    2525     error_t       error;
    2526     uint32_t      page_id;        // page index in FAT mapper
    2527     uint32_t      slot_id;        // slot index in page (1024 slots per page)
    2528     uint32_t      cluster;        // first free cluster index in FAT
    2529     uint32_t      free_clusters;  // total number of free clusters
    2530     vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters)
    2531     fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
    2532     fatfs_ctx_t * fat_fatfs_ctx;  // local pointer on FATFS context in FAT cluster
    2533     xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
    2534     cxy_t         fat_cxy;        // Fat mapper cluster identifier
    2535     xptr_t        page_xp;        // extended pointer on current page descriptor in mapper
    2536     xptr_t        slot_xp;        // extended pointer on FAT slot defined by hint
    2537     xptr_t        lock_xp;        // extended pointer on lock protecting free clusters info
    2538     xptr_t        hint_xp;        // extended pointer on free_cluster_hint in FAT cluster
    2539     xptr_t        free_xp;        // extended pointer on free_clusters_number in FAT cluster
    2540 
    2541 #if DEBUG_FATFS_CLUSTER_ALLOC
    2542 uint32_t   cycle = (uint32_t)hal_get_cycles();
    2543 thread_t * this  = CURRENT_THREAD;
    2544 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
    2545 printk("\n[%s] thread[%x,%x] enter / cycle = %d\n",
    2546 __FUNCTION__, this->process->pid, this->trdid, cycle );
    2547 #endif
    2548 
    2549     // get local pointer on VFS context (same in all clusters)
    2550     vfs_ctx = &fs_context[FS_TYPE_FATFS];
    2551 
    2552     // get local pointer on local FATFS context
    2553     loc_fatfs_ctx = vfs_ctx->extend;
    2554 
    2555     // get extended pointer on FAT mapper
    2556     fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    2557 
    2558     // get FAT cluster
    2559     fat_cxy = GET_CXY( fat_mapper_xp );
    2560    
    2561     // get local pointer on FATFS context in FAT cluster
    2562     fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
    2563 
    2564     // build relevant extended pointers on free clusters info in mapper cluster
    2565     lock_xp = XPTR( fat_cxy , &fat_fatfs_ctx->lock );
    2566     hint_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_cluster_hint );
    2567     free_xp = XPTR( fat_cxy , &fat_fatfs_ctx->free_clusters );
    2568 
    2569     // take the FAT lock in write mode
    2570     remote_rwlock_wr_acquire( lock_xp );
    2571 
    2572     // get hint and free_clusters values from FATFS context in FAT cluster
    2573     cluster       = hal_remote_l32( hint_xp ) + 1;
    2574     free_clusters = hal_remote_l32( free_xp );
    2575        
    2576 #if (DEBUG_FATFS_CLUSTER_ALLOC & 1)
    2577 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
    2578 printk("\n[%s] thread[%x,%x] get free info : hint %x / free_clusters %x\n",
    2579 __FUNCTION__, this->process->pid, this->trdid, (cluster - 1), free_clusters );
    2580 #endif
    2581 
    2582     // check "free_clusters"
    2583     if ( free_clusters == 0 )
    2584     {
    2585         printk("\n[ERROR] in %s : no more free FATFS clusters\n", __FUNCTION__ );
    2586         remote_rwlock_wr_release( lock_xp );
    2587         return -1;
    2588     }
    2589     else if ( free_clusters < CONFIG_VFS_FREE_CLUSTERS_MIN )
    2590     {
    2591         printk("\n[WARNING] in %s : only %n free FATFS clusters\n",
    2592         __FUNCTION__, CONFIG_VFS_FREE_CLUSTERS_MIN );
    2593     }
    2594 
    2595     // get page index & slot index for selected cluster
    2596     page_id  = cluster >> 10;
    2597     slot_id  = cluster & 0x3FF;
    2598 
    2599     // get relevant page descriptor from FAT mapper
    2600     page_xp = mapper_remote_get_page( fat_mapper_xp , page_id );
    2601 
    2602     if( page_xp == XPTR_NULL )
    2603     {
    2604         printk("\n[ERROR] in %s : cannot acces FAT mapper\n", __FUNCTION__ );
    2605         remote_rwlock_wr_release( lock_xp );
    2606         return -1;
    2607     }
    2608 
    2609     // build extended pointer on selected cluster slot in FAT mapper
    2610     slot_xp = ppm_page2base( page_xp ) + (slot_id << 2);
    2611          
    2612     // check selected cluster actually free
    2613     if( hal_remote_l32( slot_xp ) != FREE_CLUSTER )
    2614     {
    2615         printk("\n[ERROR] in %s : selected cluster %x not free\n", __FUNCTION__, cluster );
    2616         remote_rwlock_wr_release( lock_xp );
    2617         return -1;
    2618     }
    2619 
    2620     // update free cluster info in FATFS context and in FS_INFO sector
    2621     error = fatfs_free_clusters_decrement( XPTR( fat_cxy , fat_fatfs_ctx ) , cluster );
    2622 
    2623     if( error )
    2624     {
    2625         printk("\n[ERROR] in %s : cannot update free cluster info\n", __FUNCTION__ );
    2626         remote_rwlock_wr_release( lock_xp );
    2627         return -1;
    2628     }
    2629 
    2630     // update FAT mapper
    2631     hal_remote_s32( slot_xp , END_OF_CHAIN_CLUSTER_MAX );
    2632 
    2633     // we don't mark the FAT mapper page as dirty,
    2634     // because we synchronously update FAT on IOC device
    2635     error = fatfs_move_page( page_xp , IOC_SYNC_WRITE );
    2636 
    2637     if( error )
    2638     {
    2639         printk("\n[ERROR] in %s : cannot update FAT on IOC device\n", __FUNCTION__ );
    2640         remote_rwlock_wr_release( lock_xp );
    2641         return -1;
    2642     }
    2643 
    2644     // release FAT lock
    2645     remote_rwlock_wr_release( lock_xp );
    2646 
    2647 #if DEBUG_FATFS_CLUSTER_ALLOC
    2648 cycle = (uint32_t)hal_get_cycles();
    2649 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle )
    2650 printk("\n[%s] thread[%x,%x] exit / allocated cluster %x in FAT / cycle %d\n",
    2651 __FUNCTION__, this->process->pid, this->trdid, cluster, cycle );
    2652 #endif
    2653 
    2654     *searched_cluster = cluster;
    2655     return 0;
    2656 
    2657 }  // end fatfs_cluster_alloc()
    26582993
    26592994//////////////////////////////////////////////
    26602995error_t fatfs_release_inode( xptr_t inode_xp )
    26612996{
    2662     vfs_ctx_t   * vfs_ctx;        // local pointer on VFS context (same in all clusters).
    2663     fatfs_ctx_t * loc_fatfs_ctx;  // local pointer on local FATFS context
    2664     cxy_t         fat_cxy;        // FAT cluster identifier
    2665     xptr_t        fatfs_ctx_xp;   // extended pointer on FATFS context in FAT cluster
    2666     fatfs_ctx_t * fatfs_ctx_ptr;  // local pointer on FATFS context in FAT cluster
    2667     xptr_t        fat_mapper_xp;  // extended pointer on FAT mapper
    2668     xptr_t        lock_xp;        // extended pointer on lock protecting FAT.
    2669     xptr_t        first_xp;       // extended pointer on inode extension
    2670     uint32_t      first_cluster;  // first cluster index for released inode
    2671     vfs_inode_t * inode_ptr;      // local pointer on target inode
    2672     cxy_t         inode_cxy;      // target inode cluster identifier
     2997    vfs_ctx_t   * vfs_ctx;           // local pointer on VFS context (same in all clusters)
     2998    cxy_t         fat_cxy;           // FAT cluster identifier
     2999    fatfs_ctx_t * fatfs_ctx_ptr;     // local pointer on FATFS context in FAT cluster
     3000    xptr_t        fatfs_ctx_xp;      // extended pointer on FATFS-context in FAT cluster
     3001    mapper_t    * fat_mapper_ptr;    // local pointer on FAT mapper
     3002    xptr_t        fat_mapper_xp;     // extended pointer on FAT mapper
     3003    xptr_t        lock_xp;           // extended pointer on lock protecting FAT.
     3004    xptr_t        first_xp;          // extended pointer on inode extension
     3005    uint32_t      first_cluster_id;  // first cluster index for released inode
     3006    vfs_inode_t * inode_ptr;         // local pointer on target inode
     3007    cxy_t         inode_cxy;         // target inode cluster identifier
    26733008    error_t       error;
    26743009
     
    26803015    inode_cxy     = GET_CXY( inode_xp );
    26813016
    2682     // get first_cluster from inode extension
    2683     first_xp      = XPTR( inode_cxy , &inode_ptr->extend );
    2684     first_cluster = (uint32_t)(intptr_t)hal_remote_lpt( first_xp );
     3017    // get first_cluster_id from inode extension
     3018    first_xp         = XPTR( inode_cxy , &inode_ptr->extend );
     3019    first_cluster_id = (uint32_t)(intptr_t)hal_remote_lpt( first_xp );
    26853020
    26863021// check first cluster index
    2687 assert( (first_cluster != 0) , "inode extend is NULL\n" );
     3022assert( (first_cluster_id != 0) , "inode extend is NULL\n" );
    26883023
    26893024#if DEBUG_FATFS_RELEASE_INODE
     
    26933028vfs_inode_get_name( inode_xp , name );
    26943029if( DEBUG_FATFS_RELEASE_INODE < cycle )
    2695 printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster %x / cycle %d\n",
    2696 __FUNCTION__ , this->process->pid, this->trdid, name, first_cluster, cycle );
     3030printk("\n[%s] thread[%x,%x] enter for <%s> / first_cluster_id %x / cycle %d\n",
     3031__FUNCTION__ , this->process->pid, this->trdid, name, first_cluster_id, cycle );
    26973032#endif
    26983033
     
    27003035    vfs_ctx = &fs_context[FS_TYPE_FATFS];
    27013036
    2702     // get local pointer on local FATFS context
    2703     loc_fatfs_ctx = vfs_ctx->extend;
    2704 
    2705     // get FAT mapper cluster
    2706     fat_mapper_xp  = loc_fatfs_ctx->fat_mapper_xp;
    2707     fat_cxy        = GET_CXY( fat_mapper_xp );
     3037    // get FAT cluster
     3038    fat_cxy = CONFIG_VFS_ROOT_CXY;
     3039
     3040    // get pointers on FATFS context in FAT cluster
     3041    fatfs_ctx_ptr = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
     3042    fatfs_ctx_xp  = XPTR( fat_cxy , fatfs_ctx_ptr );
     3043
     3044    // get FAT mapper pointers
     3045    fat_mapper_ptr = hal_remote_lpt( XPTR( fat_cxy , &fatfs_ctx_ptr->fat_mapper ) );
     3046        fat_mapper_xp  = XPTR( fat_cxy , fat_mapper_ptr );
    27083047   
    2709     // get pointers on FATFS context in FAT cluster
    2710     fatfs_ctx_ptr  = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );
    2711     fatfs_ctx_xp   = XPTR( fat_cxy , fatfs_ctx_ptr );
    2712 
    2713     // get extended pointer on FAT lock in FAT cluster
     3048    // build extended pointer on FAT lock in FAT cluster
    27143049    lock_xp = XPTR( fat_cxy , &fatfs_ctx_ptr->lock );
    27153050
     
    27273062    if ( fatfs_recursive_release( fat_mapper_xp,
    27283063                                  fatfs_ctx_xp,
    2729                                   first_cluster,
     3064                                  first_cluster_id,
    27303065                                  &dirty_page_min,
    27313066                                  &dirty_page_max ) )
     
    27913126}  // end fatfs_release_inode()
    27923127
    2793 ////////////////////////////////////////////
    2794 error_t fatfs_move_page( xptr_t     page_xp,
    2795                          cmd_type_t cmd_type )
    2796 {
    2797     error_t       error;
     3128/////////////////////////////////////////////////
     3129error_t fatfs_move_page( xptr_t          page_xp,
     3130                         ioc_cmd_type_t  cmd_type )
     3131{
     3132    error_t       error = 0;
     3133
    27983134    vfs_inode_t * inode_ptr;
    27993135    mapper_t    * mapper_ptr;     
     
    28293165#if DEBUG_FATFS_MOVE_PAGE
    28303166if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2831 printk("\n[%s] thread[%x,%x] enters for %s /  page %d in FAT mapper / cycle %d\n",
     3167printk("\n[%s] thread[%x,%x] enters %s for  page %d in FAT mapper / cycle %d\n",
    28323168__FUNCTION__, this->process->pid, this->trdid, dev_ioc_cmd_str(cmd_type), page_id, cycle );
    28333169#endif
     
    28363172 
    28373173        // access IOC device
    2838         error = dev_ioc_move_data( cmd_type , buffer_xp , lba , 8 );
     3174        if     (cmd_type == IOC_SYNC_WRITE) error = dev_ioc_sync_write( buffer_xp, lba, 8 );
     3175        else if(cmd_type == IOC_SYNC_READ ) error = dev_ioc_sync_read( buffer_xp, lba, 8 );
     3176        else
     3177        {
     3178            printk("\n[ERROR] in %s : illegal asynchronous FAT access\n", __FUNCTION__ );
     3179        }
    28393180
    28403181        if( error )
    28413182        {
    2842             printk("\n[ERROR] in %s : cannot access device\n", __FUNCTION__ );
     3183            printk("\n[ERROR] in %s : cannot access IOC device\n", __FUNCTION__ );
    28433184            return -1;
    28443185        }
     
    28463187#if DEBUG_FATFS_MOVE_PAGE
    28473188if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2848 printk("\n[%s] thread[%x,%x] exit / page %d in FAT mapper\n",
    2849 __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
     3189printk("\n[%s] thread[%x,%x] exit %s for page %d in FAT mapper\n",
     3190__FUNCTION__, this->process->pid, this->trdid, dev_ioc_cmd_str(cmd_type), page_id );
    28503191#endif
    28513192
     
    28563197
    28573198#if DEBUG_FATFS_MOVE_PAGE
    2858 vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name );
    28593199if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2860 printk("\n[%s] thread[%x,%x] enters for %s / page %d in <%s> mapper/ cycle %d\n",
    2861 __FUNCTION__, this->process->pid, this->trdid,
    2862 dev_ioc_cmd_str( cmd_type ), page_id, name, cycle );
     3200{
     3201    vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name );
     3202    printk("\n[%s] thread[%x,%x] enters %s for page %d in <%s> mapper / cycle %d\n",
     3203    __FUNCTION__, this->process->pid, this->trdid,
     3204    dev_ioc_cmd_str( cmd_type ), page_id, name, cycle );
     3205}
    28633206#endif
    28643207
     
    28933236        uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id );
    28943237
    2895         // access IOC device to move 8 blocks
    2896         error = dev_ioc_move_data( cmd_type , buffer_xp , lba , 8 );
     3238        // access IOC device
     3239        if     (cmd_type == IOC_WRITE     ) error = dev_ioc_write( buffer_xp, lba, 8 );
     3240        else if(cmd_type == IOC_READ      ) error = dev_ioc_read( buffer_xp, lba, 8 );
     3241        else if(cmd_type == IOC_SYNC_READ ) error = dev_ioc_sync_read( buffer_xp, lba, 8 );
     3242        else if(cmd_type == IOC_SYNC_WRITE) error = dev_ioc_sync_write( buffer_xp, lba, 8 );
     3243        else
     3244        {
     3245            printk("\n[ERROR] in %s : illegal cmd_type\n", __FUNCTION__ );
     3246        }
    28973247
    28983248        if( error )
     
    29043254#if DEBUG_FATFS_MOVE_PAGE
    29053255if( DEBUG_FATFS_MOVE_PAGE < cycle )
    2906 vfs_inode_get_name( XPTR( page_cxy, inode_ptr ) , name );
    2907 printk("\n[%s] thread[%x,%x] exit / page %d in <%s> mapper / cluster_id %x\n",
    2908 __FUNCTION__, this->process->pid, this->trdid, page_id, name, searched_cluster_id );
     3256{
     3257    printk("\n[%s] thread[%x,%x] exit %s for page %d in <%s> mapper / cluster_id %x\n",
     3258    __FUNCTION__, this->process->pid, this->trdid,
     3259    dev_ioc_cmd_str( cmd_type ), page_id, name, searched_cluster_id );
     3260}
     3261#endif
     3262
     3263#if (DEBUG_FATFS_MOVE_PAGE & 1)
     3264if( DEBUG_FATFS_MOVE_PAGE < cycle )
     3265fatfs_display_fat( searched_cluster_id , 64 );
    29093266#endif
    29103267
Note: See TracChangeset for help on using the changeset viewer.