Changeset 657 for trunk/kernel/fs/fatfs.c
- Timestamp:
- Mar 18, 2020, 11:16:59 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/fs/fatfs.c
r656 r657 2 2 * fatfs.c - FATFS file system API implementation. 3 3 * 4 * Author Alain Greiner (2016,2017,2018,2019 )4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 122 122 for( i = nbytes ; i > 0 ; i-- ) 123 123 { 124 res = (res<<8) | hal_remote_lb( buffer_xp +offset+i-1 );124 res = (res<<8) | hal_remote_lb( buffer_xp + offset + i-1 ); 125 125 } 126 126 } … … 129 129 for( i = 0 ; i < nbytes ; i++ ) 130 130 { 131 res = (res<<8) | hal_remote_lb( buffer_xp +offset+i );131 res = (res<<8) | hal_remote_lb( buffer_xp + offset + i ); 132 132 } 133 133 } … … 135 135 136 136 } // end fatfs_get_remote_record() 137 138 /* 137 139 138 140 ////////////////////////////////////////////////////////////////////////////////////////// … … 164 166 } // end fatfs_set_record() 165 167 168 */ 169 166 170 ////////////////////////////////////////////////////////////////////////////////////////// 167 171 // This function writes one, two, or four bytes from a 32 bits integer to a remote … … 185 189 for( i = nbytes ; i > 0 ; i-- ) 186 190 { 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)) ); 188 192 } 189 193 } … … 192 196 for( i = 0 ; i < nbytes ; i++ ) 193 197 { 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)) ); 195 199 } 196 200 } … … 470 474 cxy_t fat_cxy; // FAT cluster identifier 471 475 fatfs_ctx_t * fatfs_ctx; // local pointer on FATFS context in FAT cluster 472 xptr_t fat_mapper_xp; // extended pointer on FAT mapper473 476 mapper_t * fat_mapper_ptr; // local pointer on FAT mapper 474 477 uint32_t page_id; // current page index in FAT mapper … … 482 485 fatfs_ctx = GET_PTR( fatfs_ctx_xp ); 483 486 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 ) ); 490 489 491 490 // build extended pointer on FAT mapper radix tree … … 575 574 576 575 // 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 ); 578 577 579 578 } // end fatfs_update_ioc_fsinfo() … … 581 580 ////////////////////////////////////////////////////////////////////////////////////////// 582 581 // 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. 585 587 // 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>. 589 589 // The lock protecting exclusive access to the FAT must be taken by the calling function. 590 590 ////////////////////////////////////////////////////////////////////////////////////////// 591 591 // @ fatfs_ctx_xp : extended pointer on FATFS context in FAT cluster. 592 // @ cluster 592 // @ cluster_id : recently allocated cluster index in FAT. 593 593 // @ return 0 if success, return -1 if the FS_INFO sector cannot be updated. 594 594 ////////////////////////////////////////////////////////////////////////////////////////// 595 595 static error_t fatfs_free_clusters_decrement( xptr_t fatfs_ctx_xp, 596 uint32_t cluster )596 uint32_t cluster_id ) 597 597 { 598 598 error_t error; 599 cxy_t fat_cxy; // FAT cluster identifier600 fatfs_ctx_t * fat_ctx_ptr; // local pointer on fatfs context in FAT cluster601 xptr_t fat_mapper_xp; // extendedpointer on FAT mapper602 xptr_t hint_xp; // extended pointer on "free_cluster_hint" shared variable603 xptr_t numb_xp; // extended pointer on "free_clusters" shared variable604 uint32_t numb; // "free_clusters" variable current value605 uint32_t hint; // "free_cluster_hint" variable current value606 uint32_t page_id; // page index in FAT mapper607 uint32_t slot_id; // slot index in one page of FAT (1024 slots per page)608 uint32_t page_max; // max number of pagesin FAT mapper609 xptr_t page_xp; // extended pointer on current page in FAT mapper610 xptr_t base_xp; // extended pointer on current page base611 xptr_t slot_xp; // extended pointer on current slot in FAT mapper599 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 612 612 613 613 #if DEBUG_FATFS_FREE_CLUSTERS … … 615 615 thread_t * this = CURRENT_THREAD; 616 616 if( 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 );617 printk("\n[%s] thread[%x,%x] enter for allocated cluster_id %x / cycle %d\n", 618 __FUNCTION__, this->process->pid, this->trdid, cluster_id , cycle ); 619 619 #endif 620 620 … … 627 627 numb_xp = XPTR( fat_cxy , &fat_ctx_ptr->free_clusters ); 628 628 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; 640 636 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) ) 644 641 { 645 642 // 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 ); 647 644 648 645 if( page_xp == XPTR_NULL ) … … 655 652 base_xp = ppm_page2base( page_xp ); 656 653 657 // scan FAT mapper /loop on slots658 while ( slot_id < 1024)654 // scan the FAT mapper : second loop on slots 655 while ( (slot_id < 1024) && (found == 0) ) 659 656 { 660 657 // get extended pointer on current slot … … 664 661 if ( hal_remote_l32( slot_xp ) == FREE_CLUSTER ) 665 662 { 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 } 680 695 681 696 #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", 697 if( DEBUG_FATFS_FREE_CLUSTERS < cycle ) 698 printk("\n[%s] thread[%x,%x] exit / hint %x / free %x\n", 685 699 __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; 700 hal_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 } 705 709 706 710 } // end fatfs_free_clusters_decrement() … … 709 713 // This static function increments the "free_clusters" variable, and updates the 710 714 // "free_cluster_hint" variables in the FATFS context in FAT cluster, identified 711 // by the <fat_ctx_xp> argument, when a FATFS cluster isreleased.715 // by the <fat_ctx_xp> argument, when a FATFS <cluster_id> has been released. 712 716 // If the released cluster index is smaller than the current (hint) value, 713 717 // 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. 715 720 // It can be called by a thead running in any cluster. 716 721 // The lock protecting exclusive access to the FAT must be taken by the calling function. 717 722 ////////////////////////////////////////////////////////////////////////////////////////// 718 723 // @ fatfs_ctx_xp : extended pointer on FATFS context in FAT cluster. 719 // @ cluster 724 // @ cluster_id : recently released cluster index in FAT. 720 725 // @ return 0 if success, return -1 if the FS_INFO sector cannot be updated. 721 726 ////////////////////////////////////////////////////////////////////////////////////////// 722 727 static 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 { 726 730 cxy_t fat_cxy; // FAT cluster identifier 727 731 fatfs_ctx_t * fat_ctx_ptr; // local pointer on fatfs context in FAT cluster … … 735 739 thread_t * this = CURRENT_THREAD; 736 740 if( 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 );741 printk("\n[%s] thread[%x,%x] enter for released cluster_id %x / cycle %d\n", 742 __FUNCTION__, this->process->pid, this->trdid, cluster_id , cycle ); 739 743 #endif 740 744 … … 753 757 // update "numb" and "hint" variables as required 754 758 numb++; 755 if ( (cluster - 1) < hint ) hint = cluster- 1;759 if ( (cluster_id - 1) < hint ) hint = cluster_id - 1; 756 760 757 761 // update free_clusters … … 759 763 hal_remote_s32( hint_xp , hint ); 760 764 761 // update FS_INFO sector on IOC device762 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 770 765 #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", 766 if( DEBUG_FATFS_FREE_CLUSTERS < cycle ) 767 printk("\n[%s] thread[%x,%x] exit / hint %x / free %x\n", 774 768 __FUNCTION__, this->process->pid, this->trdid, 775 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) , cycle);769 hal_remote_l32( hint_xp ), hal_remote_l32( numb_xp ) ); 776 770 #endif 777 771 … … 853 847 854 848 ////////////////////////////////////////////////////////////////////////////////////////// 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 ////////////////////////////////////////////////////////////////////////////////////////// 867 static 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 893 uint32_t cycle = (uint32_t)hal_get_cycles(); 894 thread_t * this = CURRENT_THREAD; 895 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 896 printk("\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) 929 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 930 printk("\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 1051 cycle = (uint32_t)hal_get_cycles(); 1052 if( DEBUG_FATFS_CLUSTER_ALLOC < cycle ) 1053 printk("\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 ////////////////////////////////////////////////////////////////////////////////////////// 855 1064 // This static function access the FAT (File Allocation Table), stored in the FAT mapper, 856 1065 // 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 file1066 // inode, identified by the <searched_page_id> argument that is the page index in file 858 1067 // (i.e. the page index in file mapper). The entry point in the FAT is defined by the 859 1068 // <first_cluster_id> argument, that is the cluster_id of an already allocated cluster. … … 861 1070 // fatfs_inode extension), or any page of the file whose <first_page_id> argument 862 1071 // 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. 865 1073 // The FAT mapper being a WRITE-THROUGH cache, this function updates the FAT mapper 866 1074 // from informations stored on IOC device in case of miss when scanning the FAT mapper. … … 885 1093 uint32_t current_cluster_id; // index of cluster in FATFS 886 1094 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; 887 1099 888 1100 assert( (searched_page_id > first_page_id) , … … 893 1105 thread_t * this = CURRENT_THREAD; 894 1106 if( 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 ); 1107 printk("\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, 1109 first_page_id, first_cluster_id, searched_page_id, cycle ); 897 1110 #endif 898 1111 … … 903 1116 fatfs_ctx_t * loc_fatfs_ctx = vfs_ctx->extend; 904 1117 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 ); 908 1124 909 1125 // get local pointer on FATFS context in FAT cluster … … 931 1147 932 1148 // 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 ); 934 1150 935 1151 if( current_page_xp == XPTR_NULL ) … … 942 1158 943 1159 // 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 ); 946 1162 947 1163 // get next_cluster_id from FAT slot 948 1164 uint32_t next_cluster_id = hal_remote_l32( XPTR( fat_cxy, &buffer[fat_slot_index] ) ); 949 1165 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 952 1167 if( next_cluster_id >= END_OF_CHAIN_CLUSTER_MIN ) 953 1168 { … … 956 1171 957 1172 // 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 ); 960 1175 if( error ) 961 1176 { … … 968 1183 #if (DEBUG_FATFS_GET_CLUSTER & 1) 969 1184 if( DEBUG_FATFS_GET_CLUSTER < cycle ) 970 printk("\n[%s] allocated a new cluster_id % din FATFS\n",1185 printk("\n[%s] allocated a new cluster_id %x in FATFS\n", 971 1186 __FUNCTION__, next_cluster_id ); 972 1187 #endif … … 977 1192 #if (DEBUG_FATFS_GET_CLUSTER & 1) 978 1193 if( 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 );1194 printk("\n[%s] traverse FAT / current_cluster_id %x / next_cluster_id %x\n", 1195 __FUNCTION__, current_cluster_id , next_cluster_id ); 981 1196 #endif 982 1197 … … 991 1206 #if DEBUG_FATFS_GET_CLUSTER 992 1207 if( 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 ); 1208 printk("\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, 1210 first_page_id, first_cluster_id, searched_page_id, current_cluster_id ); 995 1211 #endif 996 1212 … … 1000 1216 } // end fatfs_get_cluster() 1001 1217 1002 1003 1004 1005 1006 //////////////////////////////////////////////////////////////////////////////////////////1007 // FATFS specific extern functions1008 //////////////////////////////////////////////////////////////////////////////////////////1009 1010 ///////////////////////////////////1011 void fatfs_display_ctx( cxy_t cxy )1012 {1013 // get pointer on local FATFS context1014 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 display1064 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 context1068 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 cluster1076 fatfs_ctx_t * fat_fatfs_ctx = hal_remote_lpt( XPTR( mapper_cxy , &vfs_ctx->extend ) );1077 1078 // get current value of hint and free_clusters1079 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 mapper1083 xptr_t page_xp = mapper_remote_get_page( mapper_xp , page_id );1084 1085 // get pointers on requested page base1086 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 VFS1111 // 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_INIT1134 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 #endif1140 1141 // check argument1142 assert( (fatfs_ctx != NULL) , "pointer on FATFS context is NULL" );1143 1144 // check only cluster 0 does FATFS initialization1145 assert( (local_cxy == 0) , "only cluster 0 can initialize FATFS");1146 1147 // allocate a permanent 512 bytes buffer to store1148 // - temporarily the BOOT sector1149 // - permanently the FS_INFO sector1150 req.type = KMEM_KCM;1151 req.order = 9; // 512 bytes1152 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 device1164 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 #endif1176 1177 // get sector size from boot record1178 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 record1186 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 record1194 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 record1202 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 record1210 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 record1218 uint32_t fat_lba = fatfs_get_record( BPB_RSVDSECCNT , buffer );1219 1220 // get FS_INFO sector lba from boot record1221 uint32_t fs_info_lba = fatfs_get_record( BPB_FAT32_FSINFO , buffer );1222 1223 // load the FS_INFO record from device1224 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 record1233 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 record1241 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 itself1250 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 mapper1258 fat_mapper->inode = NULL;1259 1260 // initialize the FATFS context1261 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 #endif1279 1280 #if DEBUG_FATFS_CTX_INIT1281 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 #endif1286 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 length1304 uint32_t nb_lfn; // number or required LFN1305 char sfn[11]; // buffer for SFN name1306 uint8_t checksum; // name checksum1307 mapper_t * mapper; // loal pointer on parent inode mapper1308 xptr_t mapper_xp; // extended pointer on parent inode mapper1309 xptr_t child_xp; // extended pointer on child inode1310 cxy_t child_cxy; // child inode cluster1311 vfs_inode_t * child_ptr; // child inode local pointer1312 uint32_t size; // child inode size1313 uint32_t type; // child inode type1314 uint32_t cluster; // child inode cluster index1315 1316 #if DEBUG_FATFS_ADD_DENTRY1317 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 #endif1325 1326 // check arguments1327 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 mapper1332 mapper = inode->mapper;1333 mapper_xp = XPTR( local_cxy , mapper );1334 1335 // get extended pointers on remote child inode1336 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 inode1341 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 name1346 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 mapper1359 // - scan the entries in each page to find NO_MORE_ENTRY1360 1361 xptr_t page_xp; // extended pointer on page descriptor1362 xptr_t base_xp; // extended pointer on page base1363 uint8_t * base; // local pointer on page base (array of bytes)1364 uint32_t page_id = 0; // page index in mapper1365 uint32_t offset = 0; // position in page1366 uint32_t found = 0; // NO_MORE_ENTRY found1367 1368 // loop on pages in mapper1369 while ( found == 0 )1370 {1371 // get extended pointer on page descriptor in mapper1372 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 base1381 base_xp = ppm_page2base( page_xp );1382 base = GET_PTR( base_xp );1383 1384 // loop on directory entries in this page1385 while ( (offset < 4096) && (found == 0) )1386 {1387 if ( fatfs_get_record( LDIR_ORD, (base + offset) ) == NO_MORE_ENTRY )1388 {1389 found = 1;1390 }1391 else1392 {1393 offset = offset + 32;1394 }1395 } // end loop on entries1396 1397 if ( found == 0 )1398 {1399 page_id++;1400 offset = 0;1401 }1402 } // end loop on pages1403 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 FSM1407 // (one state per entry to be written), that is traversed as:1408 // LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE1409 // At most two pages are modified:1410 // - the page containing the NO_MORE_ENTRY is always modified1411 // - 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 state1416 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 written1422 uint32_t i; // byte index in one 32 bytes directory1423 uint32_t c; // character index in name1424 1425 while ( step )1426 {1427 // when the new child is split on two pages,1428 // we need to access a new page in mapper1429 if ( offset >= 4096 )1430 {1431 // copy the modified page to IOC device1432 fatfs_move_page( page_xp , IOC_SYNC_WRITE );1433 1434 // get the next page in FAT mapper1435 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 base1444 base_xp = ppm_page2base( page_xp );1445 base = GET_PTR( base_xp );1446 1447 // update offset1448 offset = 0;1449 }1450 1451 // compute directory entry address1452 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 #endif1460 1461 // write 32 bytes (one directory entry) per iteration1462 switch ( step )1463 {1464 case 5: // write LFN3 entry1465 {1466 c = 26;1467 // scan the 32 bytes in dir_entry1468 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 entry1491 {1492 c = 13;1493 // scan the 32 bytes in dir_entry1494 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 entry1517 {1518 c = 0;1519 // scan the 32 bytes in dir_entry1520 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 entry1543 {1544 // scan the 32 bytes in dir_entry1545 for ( i = 0 ; i < 32 ; i++ )1546 {1547 if ( i < 11 ) // 8.3 SFN1548 {1549 entry[i] = sfn[i];1550 }1551 else if (i == 11) // ATTR1552 {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.B21557 else if (i == 21) entry[i] = cluster>>24; // cluster.B31558 else if (i == 26) entry[i] = cluster>>0; // cluster.B01559 else if (i == 27) entry[i] = cluster>>8; // cluster.B11560 else if (i == 28) entry[i] = size>>0; // size.B01561 else if (i == 29) entry[i] = size>>8; // size.B11562 else if (i == 30) entry[i] = size>>16; // size.B21563 else if (i == 31) entry[i] = size>>24; // size.B31564 else entry[i] = 0x00;1565 }1566 1567 // update the "extend" field in dentry descriptor1568 dentry->extend = (void*)(intptr_t)(((page_id<<12) + offset)>>5);1569 1570 step--;1571 break;1572 }1573 case 1: // write NOMORE entry1574 {1575 entry [0] = 0x00;1576 step--;1577 break;1578 }1579 } // end switch step1580 1581 offset += 32;1582 1583 } // exit while1584 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 #endif1591 1592 // copy the modified page to the IOC device1593 fatfs_move_page( page_xp , IOC_SYNC_WRITE );1594 1595 #if DEBUG_FATFS_ADD_DENTRY1596 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 #endif1601 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 mapper1611 mapper_t * mapper; // local pointer on mapper1612 xptr_t page_xp; // extended pointer on mapper page descriptor1613 xptr_t base_xp; // extended pointer on mapper page base1614 uint8_t * base; // local pointer on mapper page base1615 1616 #if DEBUG_FATFS_REMOVE_DENTRY1617 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 #endif1625 1626 // check arguments1627 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 mapper1633 mapper = inode->mapper;1634 mapper_xp = XPTR( local_cxy , mapper );1635 1636 // compute number of LFN entries1637 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 entries1646 // 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->extend1651 uint32_t dentry_id = (uint32_t)(intptr_t)dentry->extend;1652 1653 // get page index and offset in parent directory mapper1654 uint32_t page_id = dentry_id >> 7;1655 uint32_t offset = (dentry_id & 0x7F)<<5;1656 1657 #if DEBUG_FATFS_REMOVE_DENTRY & 11658 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 #endif1662 1663 // get extended pointer on page descriptor from parent directory mapper1664 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 base1673 base_xp = ppm_page2base( page_xp );1674 base = GET_PTR( base_xp );1675 1676 // invalidate NORMAL entry in directory cache1677 base[offset] = 0xE5;1678 1679 // invalidate LFN entries1680 while ( nb_lfn )1681 {1682 if (offset == 0) // we must load page (page_id - 1)1683 {1684 1685 // check page_id1686 assert( (page_id > 0), "page_id and offset cannot be both 0\n" );1687 1688 // copy the modified page to the IOC device1689 fatfs_move_page( page_xp , IOC_SYNC_WRITE );1690 1691 // get extended pointer on page descriptor from parent directory mapper1692 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 base1701 base_xp = ppm_page2base( page_xp );1702 base = GET_PTR( base_xp );1703 1704 // update offset1705 offset = 4096;1706 }1707 1708 offset = offset - 32;1709 1710 // check for LFN entry1711 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 entry1715 base[offset] = 0xE5;1716 1717 nb_lfn--;1718 }1719 1720 // copy the modified page to the IOC device1721 fatfs_move_page( page_xp , IOC_SYNC_WRITE );1722 1723 1724 #if DEBUG_FATFS_REMOVE_DENTRY1725 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 #endif1730 1731 return 0;1732 1733 } // end fatfs_remove_dentry1734 1735 1736 1218 ////////////////////////////////////////////////////////////////////////////////////////////// 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. 1743 1226 ////////////////////////////////////////////////////////////////////////////////////////////// 1744 // @ mapper : [in] localpointer on directory mapper.1227 // @ mapper_xp : [in] extended pointer on directory mapper. 1745 1228 // @ name : [in] searched directory entry name. 1746 1229 // @ entry : [out] buffer for the pointer on the 32 bytes directory entry (when found). … … 1748 1231 // @ return 0 if found / return 1 if not found / return -1 if mapper access error. 1749 1232 ////////////////////////////////////////////////////////////////////////////////////////////// 1750 static error_t fatfs_scan_directory( mapper_t * mapper,1233 static error_t fatfs_scan_directory( xptr_t mapper_xp, 1751 1234 char * name, 1752 1235 uint8_t ** entry, 1753 1236 uint32_t * index ) 1754 1237 { 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 1241 assert( (mapper_xp != XPTR_NULL) , "mapper pointer is NULL\n" ); 1242 assert( (name != NULL ) , "child name is undefined\n" ); 1763 1243 1764 1244 #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 ); 1245 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1246 uint32_t cycle = (uint32_t)hal_get_cycles(); 1247 thread_t * this = CURRENT_THREAD; 1248 mapper_t * mapper_ptr = GET_PTR( mapper_xp ); 1249 cxy_t mapper_cxy = GET_CXY( mapper_xp ); 1250 vfs_inode_t * inode_ptr = hal_remote_lpt( XPTR( mapper_cxy , &mapper_ptr->inode ) ); 1251 vfs_inode_get_name( XPTR( mapper_cxy , inode_ptr ) , parent_name ); 1769 1252 if( DEBUG_FATFS_SCAN_DIRECTORY < cycle ) 1770 1253 printk("\n[%s] thread[%x,%x] enter to search child <%s> in parent <%s> / cycle %d\n", … … 1777 1260 char lfn2[16]; // buffer for one partial cname 1778 1261 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 1783 1264 uint8_t attr; // directory entry ATTR field 1784 1265 uint8_t ord; // directory entry ORD field … … 1789 1270 uint32_t offset = 0; // byte offset in page 1790 1271 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 1792 1275 1793 1276 // scan the mapper pages … … 1795 1278 { 1796 1279 // get one page 1797 page_xp = mapper_ remote_get_page( mapper_xp , page_id );1280 page_xp = mapper_get_page( mapper_xp , page_id ); 1798 1281 1799 1282 if( page_xp == XPTR_NULL) … … 1804 1287 // get page base 1805 1288 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) 1809 1291 if( DEBUG_FATFS_SCAN_DIRECTORY < cycle ) 1810 1292 mapper_display_page( mapper_xp , page_xp , 256 ); … … 1813 1295 while( (offset < 4096) && (found == 0) ) 1814 1296 { 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 ); 1817 1303 1818 1304 if (ord == NO_MORE_ENTRY) // no more entry => break … … 1832 1318 seq = ord & 0x3; 1833 1319 lfn = (seq > lfn) ? seq : lfn; 1834 if ( seq == 1 ) fatfs_get_name_from_long( b ase + offset, lfn1 );1835 else if ( seq == 2 ) fatfs_get_name_from_long( b ase + offset, lfn2 );1836 else if ( seq == 3 ) fatfs_get_name_from_long( b ase + 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 ); 1837 1323 offset = offset + 32; 1838 1324 } … … 1842 1328 if ( lfn == 0 ) 1843 1329 { 1844 fatfs_get_name_from_short( b ase + offset, cname );1330 fatfs_get_name_from_short( buf , cname ); 1845 1331 } 1846 1332 else if ( lfn == 1 ) … … 1863 1349 if ( strcmp( name , cname ) == 0 ) 1864 1350 { 1351 uint8_t * base = GET_PTR( base_xp ); 1865 1352 *entry = base + offset; 1866 *index = ( (page_id<<12) + offset)>>5;1867 found 1353 *index = ( (page_id << 12) + offset ) >> 5; 1354 found = 1; 1868 1355 } 1869 1356 offset = offset + 32; 1870 1357 lfn = 0; 1871 1358 } 1359 1872 1360 } // end loop on directory entries in page 1873 1361 … … 1881 1369 1882 1370 #if DEBUG_FATFS_SCAN_DIRECTORY 1883 cycle = (uint32_t)hal_get_cycles();1884 1371 if( DEBUG_FATFS_SCAN_DIRECTORY < cycle ) 1885 1372 printk("\n[%s] thread[%x,%x] exit / found child <%s> in <%s>\n", … … 1892 1379 1893 1380 #if DEBUG_FATFS_SCAN_DIRECTORY 1894 cycle = (uint32_t)hal_get_cycles();1895 1381 if( DEBUG_FATFS_SCAN_DIRECTORY < cycle ) 1896 1382 printk("\n[%s] thread[%x,%x] exit / child <%s> in <%s> not found\n", … … 1909 1395 1910 1396 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 /////////////////////////////////// 1402 void 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 ////////////////////////////////////////// 1448 void 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 ///////////////////////////////////// 1526 error_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 1950 1541 uint32_t cycle = (uint32_t)hal_get_cycles(); 1951 1542 thread_t * this = CURRENT_THREAD; 1952 vfs_inode_get_name( XPTR( local_cxy , parent_inode ) , parent_name ); 1953 if( DEBUG_FATFS_NEW_DENTRY < cycle ) 1543 if( DEBUG_FATFS_SYNC_FSINFO < cycle ) 1544 printk("\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 1575 if( DEBUG_FATFS_SYNC_FSINFO < cycle ) 1576 printk("\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, 1578 ctx_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 1609 cycle = (uint32_t)hal_get_cycles(); 1610 if( DEBUG_FATFS_SYNC_FSINFO < cycle ) 1611 printk("\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 ///////////////////////////////////// 1630 xptr_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 /////////////////////////////////////////////// 1644 error_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 1660 uint32_t cycle = (uint32_t)hal_get_cycles(); 1661 thread_t * this = CURRENT_THREAD; 1662 if( DEBUG_FATFS_CTX_INIT < cycle ) 1663 printk("\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) 1694 uint8_t bs[256]; 1695 hal_remote_memcpy( XPTR( local_cxy , bs ) , buffer_xp , 256 ); 1696 if( DEBUG_FATFS_CTX_INIT < cycle ) 1697 putb( "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) 1792 if( DEBUG_FATFS_CTX_INIT < cycle ) 1793 printk("\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 1817 if( DEBUG_FATFS_CTX_INIT < cycle ) 1818 printk("\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 ////////////////////////////////////////////// 1827 void 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 ///////////////////////////////////////////////////////// 1859 error_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 1884 assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" ); 1885 assert( (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 1900 uint32_t cycle = (uint32_t)hal_get_cycles(); 1901 thread_t * this = CURRENT_THREAD; 1902 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; 1903 vfs_inode_get_name( parent_inode_xp , parent_name ); 1904 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 1905 printk("\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) 1914 mapper_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) 1984 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 1985 printk("\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) 2042 cycle = (uint32_t)hal_get_cycles(); 2043 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 2044 printk("\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 2203 cycle = (uint32_t)hal_get_cycles(); 2204 if( DEBUG_FATFS_ADD_DENTRY < cycle ) 2205 printk("\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) 2210 mapper_display_page( mapper_xp , 0 , 512 ); 2211 #endif 2212 2213 return 0; 2214 2215 } // end fatfs_add_dentry() 2216 2217 //////////////////////////////////////////////////////////// 2218 error_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 2238 assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" ); 2239 assert( (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 2254 uint32_t cycle = (uint32_t)hal_get_cycles(); 2255 thread_t * this = CURRENT_THREAD; 2256 char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; 2257 vfs_inode_get_name( parent_inode_xp , parent_name ); 2258 if( DEBUG_FATFS_REMOVE_DENTRY < cycle ) 2259 printk("\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 2290 if( DEBUG_FATFS_REMOVE_DENTRY < cycle ) 2291 printk("\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 2346 assert( (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 2366 cycle = (uint32_t)hal_get_cycles(); 2367 if( DEBUG_FATFS_REMOVE_DENTRY < cycle ) 2368 printk("\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 ///////////////////////////////////////////////////////////////////// 2377 error_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 2397 assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp is NULL\n" ); 2398 assert( (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 2414 uint32_t cycle = (uint32_t)hal_get_cycles(); 2415 thread_t * this = CURRENT_THREAD; 2416 if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle ) 1954 2417 printk("\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 ); 1956 2419 #endif 1957 2420 1958 2421 // 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 ); 2007 2445 2008 2446 // update the child inode "type", "size", and "extend" fields 2009 2447 vfs_inode_type_t type = (is_dir) ? INODE_TYPE_DIR : INODE_TYPE_FILE; 2010 2448 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 ); 2014 2452 2015 2453 // 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 2019 2457 cycle = (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 } 2458 if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle ) 2459 printk("\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) 2464 if( DEBUG_FATFS_NEW_DENTRY_FROM < cycle ) 2465 fatfs_display_fat( cluster_id , 32 ); 2032 2466 #endif 2033 2467 2034 2468 return 0; 2035 2469 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 /////////////////////////////////////////////////////////////////// 2473 error_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]; 2049 2486 2050 2487 // check arguments 2051 assert( (inode != NULL) , "inode is NULL\n" ); 2052 assert( (dentry != NULL) , "dentry is NULL\n" ); 2488 assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" ); 2489 assert( (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 2505 uint32_t cycle = (uint32_t)hal_get_cycles(); 2506 thread_t * this = CURRENT_THREAD; 2507 if( DEBUG_FATFS_NEW_DENTRY_TO_MAP < cycle ) 2508 printk("\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 2538 if( DEBUG_FATFS_NEW_DENTRY_TO_MAP < cycle ) 2539 printk("\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 //////////////////////////////////////////////////////////// 2549 error_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 2576 assert( (parent_inode_xp != XPTR_NULL) , "parent_inode_xp argument is NULL\n" ); 2577 assert( (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 ); 2053 2589 2054 2590 #if DEBUG_FATFS_UPDATE_DENTRY 2055 2591 uint32_t cycle = (uint32_t)hal_get_cycles(); 2056 2592 thread_t * this = CURRENT_THREAD; 2057 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );2058 2593 if( 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 ); 2594 printk("\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 ); 2079 2625 2080 2626 // update dentry in mapper & device only if required 2081 if( size != current_size )2627 if( new_size != current_size ) 2082 2628 { 2083 2629 // 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 2093 2633 error = fatfs_move_page( page_xp , IOC_SYNC_WRITE ); 2094 2634 2095 2635 if( error ) 2096 2636 { 2097 vfs_inode_get_name( XPTR( local_cxy , inode ) , dir_name );2098 2637 printk("\n[ERROR] in %s : cannot update parent directory <%s> on device\n", 2099 __FUNCTION__, dir_name );2638 __FUNCTION__, parent_name ); 2100 2639 return -1; 2101 2640 } … … 2105 2644 cycle = (uint32_t)hal_get_cycles(); 2106 2645 if( 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 );2646 printk("\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 ); 2109 2648 #endif 2110 2649 … … 2168 2707 { 2169 2708 // 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 ); 2171 2710 2172 2711 if( page_xp == XPTR_NULL) return -1; … … 2273 2812 } // end fatfs_get_user_dir() 2274 2813 2275 /////////////////////////////////////////////// 2276 error_t fatfs_sync_inode( vfs_inode_t * inode ) 2277 { 2814 /////////////////////////////////////////// 2815 error_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; 2278 2829 2279 2830 // 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" ); 2831 assert( (inode_xp != XPTR_NULL) , "inode pointer undefined\n" ); 2283 2832 2284 2833 #if DEBUG_FATFS_SYNC_INODE … … 2286 2835 uint32_t cycle = (uint32_t)hal_get_cycles(); 2287 2836 thread_t * this = CURRENT_THREAD; 2288 vfs_inode_get_name( XPTR( local_cxy , inode ), name );2837 vfs_inode_get_name( inode_xp , name ); 2289 2838 if( DEBUG_FATFS_SYNC_INODE < cycle ) 2290 2839 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n", … … 2292 2841 #endif 2293 2842 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 2850 assert( (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 2856 assert( (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++; 2306 2861 2307 // get pointeron mapper radix tree2308 grdxt_t * rt = &mapper->rt;2862 // build pointers on mapper radix tree 2863 rt_xp = XPTR( inode_cxy , &mapper->rt ); 2309 2864 2310 2865 // scan all pages 2311 for( page_id = 0 ; page_id < pages ; page_id++ )2866 for( page_id = 0 ; page_id < npages ; page_id++ ) 2312 2867 { 2313 2868 // get page descriptor from mapper 2314 page = grdxt_lookup( rt, page_id );2869 page_xp = grdxt_remote_lookup( rt_xp , page_id ); 2315 2870 2316 2871 // 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 ) 2320 2881 { 2321 2882 2322 2883 #if (DEBUG_FATFS_SYNC_INODE & 1) 2323 2884 if( DEBUG_FATFS_SYNC_INODE < cycle ) 2324 printk("\n[%s] thread[%x,%x] synchronizes page %d from<%s> mapper to IOC device\n",2885 printk("\n[%s] thread[%x,%x] synchronizes page %d of <%s> mapper to IOC device\n", 2325 2886 __FUNCTION__, page_id, name ); 2326 2887 #endif 2327 // build extended pointer on page descriptor2328 xptr_t page_xp = XPTR( local_cxy , page );2329 2330 2888 // move page from mapper to device 2331 2889 error = fatfs_move_page( page_xp , IOC_WRITE ); … … 2342 2900 cycle = (uint32_t)hal_get_cycles(); 2343 2901 if( 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);2902 printk("\n[%s] thread[%x,%x] exit for <%s>\n", 2903 __FUNCTION__ , this->process->pid, this->trdid, name ); 2346 2904 #endif 2347 2905 … … 2349 2907 2350 2908 } // end fatfs_sync_inode() 2351 2352 2353 2354 2355 2356 2909 2357 2910 ////////////////////////////// 2358 2911 error_t fatfs_sync_fat( void ) 2359 2912 { 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; 2360 2924 2361 2925 #if DEBUG_FATFS_SYNC_FAT … … 2366 2930 __FUNCTION__ , this->process->pid, this->trdid, cycle ); 2367 2931 #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 2382 2941 // get pointers on remote FAT mapper radix tree 2383 2942 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 { 2400 2963 2401 2964 #if (DEBUG_FATFS_SYNC_FAT & 1) … … 2404 2967 __FUNCTION__, page_id ); 2405 2968 #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 2415 2981 } // end loop on pages 2416 2982 … … 2418 2984 cycle = (uint32_t)hal_get_cycles(); 2419 2985 if( DEBUG_FATFS_SYNC_FAT < cycle ) 2420 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",2421 __FUNCTION__ , this->process->pid, this->trdid , cycle);2986 printk("\n[%s] thread[%x,%x] exit\n", 2987 __FUNCTION__ , this->process->pid, this->trdid ); 2422 2988 #endif 2423 2989 … … 2425 2991 2426 2992 } // 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 02433 uint32_t ctx_free_clusters; // number of free clusters from fatfs context2434 uint32_t ctx_free_cluster_hint; // free cluster hint from fatfs context2435 uint32_t ioc_free_clusters; // number of free clusters from fatfs context2436 uint32_t ioc_free_cluster_hint; // free cluster hint from fatfs context2437 uint32_t fs_info_lba; // lba of FS_INFO sector on IOC device2438 uint8_t * fs_info_buffer; // local pointer on FS_INFO buffer in cluster 02439 xptr_t fs_info_buffer_xp; // extended pointer on FS_INFO buffer in cluster 02440 uint8_t tmp_buf[512]; // 512 bytes temporary buffer2441 xptr_t tmp_buf_xp; // extended pointer on temporary buffer2442 2443 #if DEBUG_FATFS_SYNC_FSINFO2444 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 #endif2450 2451 // get pointer on fatfs context in cluster 02452 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 02455 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_lba2459 fs_info_lba = hal_remote_l32( XPTR( 0 , &fatfs_ctx_ptr->fs_info_lba ) );2460 2461 // build extended pointer on temporary buffer2462 tmp_buf_xp = XPTR( local_cxy , tmp_buf );2463 2464 // copy FS_INFO sector from IOC to local buffer2465 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 IOC2474 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_FSINFO2478 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 #endif2483 2484 // check values2485 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 02494 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 02498 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 device2502 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_FSINFO2512 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 #endif2517 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 mapper2527 uint32_t slot_id; // slot index in page (1024 slots per page)2528 uint32_t cluster; // first free cluster index in FAT2529 uint32_t free_clusters; // total number of free clusters2530 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 context2532 fatfs_ctx_t * fat_fatfs_ctx; // local pointer on FATFS context in FAT cluster2533 xptr_t fat_mapper_xp; // extended pointer on FAT mapper2534 cxy_t fat_cxy; // Fat mapper cluster identifier2535 xptr_t page_xp; // extended pointer on current page descriptor in mapper2536 xptr_t slot_xp; // extended pointer on FAT slot defined by hint2537 xptr_t lock_xp; // extended pointer on lock protecting free clusters info2538 xptr_t hint_xp; // extended pointer on free_cluster_hint in FAT cluster2539 xptr_t free_xp; // extended pointer on free_clusters_number in FAT cluster2540 2541 #if DEBUG_FATFS_CLUSTER_ALLOC2542 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 #endif2548 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 context2553 loc_fatfs_ctx = vfs_ctx->extend;2554 2555 // get extended pointer on FAT mapper2556 fat_mapper_xp = loc_fatfs_ctx->fat_mapper_xp;2557 2558 // get FAT cluster2559 fat_cxy = GET_CXY( fat_mapper_xp );2560 2561 // get local pointer on FATFS context in FAT cluster2562 fat_fatfs_ctx = hal_remote_lpt( XPTR( fat_cxy , &vfs_ctx->extend ) );2563 2564 // build relevant extended pointers on free clusters info in mapper cluster2565 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 mode2570 remote_rwlock_wr_acquire( lock_xp );2571 2572 // get hint and free_clusters values from FATFS context in FAT cluster2573 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 #endif2581 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 cluster2596 page_id = cluster >> 10;2597 slot_id = cluster & 0x3FF;2598 2599 // get relevant page descriptor from FAT mapper2600 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 mapper2610 slot_xp = ppm_page2base( page_xp ) + (slot_id << 2);2611 2612 // check selected cluster actually free2613 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 sector2621 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 mapper2631 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 device2635 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 lock2645 remote_rwlock_wr_release( lock_xp );2646 2647 #if DEBUG_FATFS_CLUSTER_ALLOC2648 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 #endif2653 2654 *searched_cluster = cluster;2655 return 0;2656 2657 } // end fatfs_cluster_alloc()2658 2993 2659 2994 ////////////////////////////////////////////// 2660 2995 error_t fatfs_release_inode( xptr_t inode_xp ) 2661 2996 { 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 context2664 cxy_t fat_cxy; // FAT cluster identifier2665 xptr_t fatfs_ctx_xp; // extended pointer on FATFScontext in FAT cluster2666 fatfs_ctx_t * fatfs_ctx_ptr; // local pointer on FATFS context in FAT cluster2667 xptr_t fat_mapper_xp; // extended pointer on FAT mapper2668 xptr_t lock_xp; // extended pointer on lock protecting FAT.2669 xptr_t first_xp; // extended pointer on inode extension2670 uint32_t first_cluster ; // first cluster index for released inode2671 vfs_inode_t * inode_ptr; // local pointer on target inode2672 cxy_t inode_cxy; // target inode cluster identifier2997 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 2673 3008 error_t error; 2674 3009 … … 2680 3015 inode_cxy = GET_CXY( inode_xp ); 2681 3016 2682 // get first_cluster from inode extension2683 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 ); 2685 3020 2686 3021 // check first cluster index 2687 assert( (first_cluster != 0) , "inode extend is NULL\n" );3022 assert( (first_cluster_id != 0) , "inode extend is NULL\n" ); 2688 3023 2689 3024 #if DEBUG_FATFS_RELEASE_INODE … … 2693 3028 vfs_inode_get_name( inode_xp , name ); 2694 3029 if( 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 );3030 printk("\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 ); 2697 3032 #endif 2698 3033 … … 2700 3035 vfs_ctx = &fs_context[FS_TYPE_FATFS]; 2701 3036 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 ); 2708 3047 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 2714 3049 lock_xp = XPTR( fat_cxy , &fatfs_ctx_ptr->lock ); 2715 3050 … … 2727 3062 if ( fatfs_recursive_release( fat_mapper_xp, 2728 3063 fatfs_ctx_xp, 2729 first_cluster ,3064 first_cluster_id, 2730 3065 &dirty_page_min, 2731 3066 &dirty_page_max ) ) … … 2791 3126 } // end fatfs_release_inode() 2792 3127 2793 //////////////////////////////////////////// 2794 error_t fatfs_move_page( xptr_t page_xp, 2795 cmd_type_t cmd_type ) 2796 { 2797 error_t error; 3128 ///////////////////////////////////////////////// 3129 error_t fatfs_move_page( xptr_t page_xp, 3130 ioc_cmd_type_t cmd_type ) 3131 { 3132 error_t error = 0; 3133 2798 3134 vfs_inode_t * inode_ptr; 2799 3135 mapper_t * mapper_ptr; … … 2829 3165 #if DEBUG_FATFS_MOVE_PAGE 2830 3166 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 2831 printk("\n[%s] thread[%x,%x] enters for %s /page %d in FAT mapper / cycle %d\n",3167 printk("\n[%s] thread[%x,%x] enters %s for page %d in FAT mapper / cycle %d\n", 2832 3168 __FUNCTION__, this->process->pid, this->trdid, dev_ioc_cmd_str(cmd_type), page_id, cycle ); 2833 3169 #endif … … 2836 3172 2837 3173 // 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 } 2839 3180 2840 3181 if( error ) 2841 3182 { 2842 printk("\n[ERROR] in %s : cannot access device\n", __FUNCTION__ );3183 printk("\n[ERROR] in %s : cannot access IOC device\n", __FUNCTION__ ); 2843 3184 return -1; 2844 3185 } … … 2846 3187 #if DEBUG_FATFS_MOVE_PAGE 2847 3188 if( 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);3189 printk("\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 ); 2850 3191 #endif 2851 3192 … … 2856 3197 2857 3198 #if DEBUG_FATFS_MOVE_PAGE 2858 vfs_inode_get_name( XPTR( page_cxy , inode_ptr ) , name );2859 3199 if( 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 } 2863 3206 #endif 2864 3207 … … 2893 3236 uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id ); 2894 3237 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 } 2897 3247 2898 3248 if( error ) … … 2904 3254 #if DEBUG_FATFS_MOVE_PAGE 2905 3255 if( 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) 3264 if( DEBUG_FATFS_MOVE_PAGE < cycle ) 3265 fatfs_display_fat( searched_cluster_id , 64 ); 2909 3266 #endif 2910 3267
Note: See TracChangeset
for help on using the changeset viewer.